From aadadf0fdab98a5cdda479da0bc5386f79f1ba08 Mon Sep 17 00:00:00 2001 From: DuckPuppy Date: Fri, 8 Jun 2012 15:58:33 -0400 Subject: [PATCH] Added command-t and vim-rvm --- vim/bundle/Command-T/.gitignore | 3 + vim/bundle/Command-T/.gitmodules | 6 + vim/bundle/Command-T/.mailmap | 5 + vim/bundle/Command-T/.rspec | 1 + vim/bundle/Command-T/.vim_org.yml | 2 + vim/bundle/Command-T/Gemfile | 5 + vim/bundle/Command-T/Gemfile.lock | 26 + vim/bundle/Command-T/LICENSE | 22 + vim/bundle/Command-T/Makefile | 21 + vim/bundle/Command-T/README.txt | 1 + vim/bundle/Command-T/Rakefile | 217 ++ vim/bundle/Command-T/bin/.gitignore | 2 + vim/bundle/Command-T/command-t.gemspec | 37 + vim/bundle/Command-T/compile-test.sh | 10 + vim/bundle/Command-T/doc/.gitignore | 1 + vim/bundle/Command-T/doc/command-t.txt | 896 +++++ vim/bundle/Command-T/fixtures/bar/abc | 1 + vim/bundle/Command-T/fixtures/bar/xyz | 1 + vim/bundle/Command-T/fixtures/baz | 1 + vim/bundle/Command-T/fixtures/bing | 1 + vim/bundle/Command-T/fixtures/foo/alpha/t1 | 1 + vim/bundle/Command-T/fixtures/foo/alpha/t2 | 1 + vim/bundle/Command-T/fixtures/foo/beta | 1 + vim/bundle/Command-T/multi-spec.sh | 25 + vim/bundle/Command-T/plugin/command-t.vim | 186 ++ .../Command-T/ruby/command-t/.gitignore | 6 + .../Command-T/ruby/command-t/controller.rb | 357 ++ vim/bundle/Command-T/ruby/command-t/depend | 24 + vim/bundle/Command-T/ruby/command-t/ext.c | 65 + vim/bundle/Command-T/ruby/command-t/ext.h | 36 + .../Command-T/ruby/command-t/extconf.rb | 34 + vim/bundle/Command-T/ruby/command-t/finder.rb | 54 + .../ruby/command-t/finder/buffer_finder.rb | 35 + .../ruby/command-t/finder/file_finder.rb | 39 + .../ruby/command-t/finder/jump_finder.rb | 35 + .../ruby/command-t/finder/tag_finder.rb | 44 + vim/bundle/Command-T/ruby/command-t/match.c | 189 ++ vim/bundle/Command-T/ruby/command-t/match.h | 29 + .../Command-T/ruby/command-t/match_window.rb | 445 +++ vim/bundle/Command-T/ruby/command-t/matcher.c | 164 + vim/bundle/Command-T/ruby/command-t/matcher.h | 30 + vim/bundle/Command-T/ruby/command-t/prompt.rb | 165 + .../Command-T/ruby/command-t/ruby_compat.h | 49 + .../Command-T/ruby/command-t/scanner.rb | 28 + .../ruby/command-t/scanner/buffer_scanner.rb | 42 + .../ruby/command-t/scanner/file_scanner.rb | 101 + .../ruby/command-t/scanner/jump_scanner.rb | 54 + .../ruby/command-t/scanner/tag_scanner.rb | 49 + .../Command-T/ruby/command-t/settings.rb | 77 + vim/bundle/Command-T/ruby/command-t/stub.rb | 42 + vim/bundle/Command-T/ruby/command-t/vim.rb | 59 + .../ruby/command-t/vim/path_utilities.rb | 40 + .../Command-T/ruby/command-t/vim/screen.rb | 32 + .../Command-T/ruby/command-t/vim/window.rb | 38 + .../spec/command-t/controller_spec.rb | 102 + .../command-t/finder/buffer_finder_spec.rb | 78 + .../spec/command-t/finder/file_finder_spec.rb | 80 + .../Command-T/spec/command-t/match_spec.rb | 236 ++ .../Command-T/spec/command-t/matcher_spec.rb | 78 + .../command-t/scanner/buffer_scanner_spec.rb | 54 + .../command-t/scanner/file_scanner_spec.rb | 83 + vim/bundle/Command-T/spec/spec_helper.rb | 38 + vim/bundle/Command-T/spec/vim_formatter.rb | 41 + vim/bundle/vim-ruby-debugger/.gitattributes | 2 - vim/bundle/vim-ruby-debugger/.gitignore | 4 - vim/bundle/vim-ruby-debugger/README.md | 113 - .../autoload/ruby_debugger.vim | 2055 ------------ .../vim-ruby-debugger/bin/ruby_debugger.rb | 190 -- .../vim-ruby-debugger/doc/ruby_debugger.txt | 357 -- .../plugin/ruby_debugger.vim | 30 - .../additionals/autoload/ruby_debugger.vim | 2906 ----------------- .../src/additionals/bin/socket | Bin 7865 -> 0 bytes vim/bundle/vim-ruby-debugger/src/collector.rb | 45 - vim/bundle/vim-ruby-debugger/src/notifier | 5 - .../src/ruby_debugger/after.vim | 45 - .../src/ruby_debugger/before.vim | 77 - .../src/ruby_debugger/breakpoint.vim | 118 - .../src/ruby_debugger/commands.vim | 186 -- .../src/ruby_debugger/common.vim | 303 -- .../src/ruby_debugger/exception.vim | 33 - .../src/ruby_debugger/frame.vim | 70 - .../src/ruby_debugger/init.vim | 29 - .../src/ruby_debugger/logger.vim | 30 - .../src/ruby_debugger/public.vim | 279 -- .../src/ruby_debugger/queue.vim | 49 - .../src/ruby_debugger/server.vim | 141 - .../src/ruby_debugger/var.vim | 34 - .../src/ruby_debugger/var_child.vim | 164 - .../src/ruby_debugger/var_parent.vim | 122 - .../src/ruby_debugger/window.vim | 191 -- .../src/ruby_debugger/window_breakpoints.vim | 70 - .../src/ruby_debugger/window_frames.vim | 53 - .../src/ruby_debugger/window_variables.vim | 72 - .../src/ruby_debugger_autoload_plan.txt | 18 - .../src/ruby_debugger_plugin_plan.txt | 1 - .../vim-ruby-debugger/src/ruby_test_plan.txt | 8 - vim/bundle/vim-ruby-debugger/src/socket.c | 78 - .../src/tests/breakpoint.vim | 215 -- .../vim-ruby-debugger/src/tests/command.vim | 18 - .../src/tests/exceptions.vim | 49 - .../vim-ruby-debugger/src/tests/frames.vim | 85 - .../vim-ruby-debugger/src/tests/framework.vim | 125 - .../vim-ruby-debugger/src/tests/mock.vim | 94 - .../vim-ruby-debugger/src/tests/server.vim | 48 - .../vim-ruby-debugger/src/tests/variables.vim | 210 -- vim/bundle/vim-rvm/.gitignore | 1 + vim/bundle/vim-rvm/README.markdown | 74 + vim/bundle/vim-rvm/doc/rvm.txt | 35 + vim/bundle/vim-rvm/plugin/rvm.vim | 156 + vim/update_bundles.rb | 5 +- vimrc | 44 +- 111 files changed, 4937 insertions(+), 8725 deletions(-) create mode 100644 vim/bundle/Command-T/.gitignore create mode 100644 vim/bundle/Command-T/.gitmodules create mode 100644 vim/bundle/Command-T/.mailmap create mode 100644 vim/bundle/Command-T/.rspec create mode 100644 vim/bundle/Command-T/.vim_org.yml create mode 100644 vim/bundle/Command-T/Gemfile create mode 100644 vim/bundle/Command-T/Gemfile.lock create mode 100644 vim/bundle/Command-T/LICENSE create mode 100644 vim/bundle/Command-T/Makefile create mode 120000 vim/bundle/Command-T/README.txt create mode 100644 vim/bundle/Command-T/Rakefile create mode 100644 vim/bundle/Command-T/bin/.gitignore create mode 100644 vim/bundle/Command-T/command-t.gemspec create mode 100755 vim/bundle/Command-T/compile-test.sh create mode 100644 vim/bundle/Command-T/doc/.gitignore create mode 100644 vim/bundle/Command-T/doc/command-t.txt create mode 100644 vim/bundle/Command-T/fixtures/bar/abc create mode 100644 vim/bundle/Command-T/fixtures/bar/xyz create mode 100644 vim/bundle/Command-T/fixtures/baz create mode 100644 vim/bundle/Command-T/fixtures/bing create mode 100644 vim/bundle/Command-T/fixtures/foo/alpha/t1 create mode 100644 vim/bundle/Command-T/fixtures/foo/alpha/t2 create mode 100644 vim/bundle/Command-T/fixtures/foo/beta create mode 100755 vim/bundle/Command-T/multi-spec.sh create mode 100644 vim/bundle/Command-T/plugin/command-t.vim create mode 100644 vim/bundle/Command-T/ruby/command-t/.gitignore create mode 100644 vim/bundle/Command-T/ruby/command-t/controller.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/depend create mode 100644 vim/bundle/Command-T/ruby/command-t/ext.c create mode 100644 vim/bundle/Command-T/ruby/command-t/ext.h create mode 100644 vim/bundle/Command-T/ruby/command-t/extconf.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/finder.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/finder/buffer_finder.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/finder/file_finder.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/finder/jump_finder.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/finder/tag_finder.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/match.c create mode 100644 vim/bundle/Command-T/ruby/command-t/match.h create mode 100644 vim/bundle/Command-T/ruby/command-t/match_window.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/matcher.c create mode 100644 vim/bundle/Command-T/ruby/command-t/matcher.h create mode 100644 vim/bundle/Command-T/ruby/command-t/prompt.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/ruby_compat.h create mode 100644 vim/bundle/Command-T/ruby/command-t/scanner.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/scanner/buffer_scanner.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/scanner/file_scanner.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/scanner/jump_scanner.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/scanner/tag_scanner.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/settings.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/stub.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/vim.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/vim/path_utilities.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/vim/screen.rb create mode 100644 vim/bundle/Command-T/ruby/command-t/vim/window.rb create mode 100644 vim/bundle/Command-T/spec/command-t/controller_spec.rb create mode 100644 vim/bundle/Command-T/spec/command-t/finder/buffer_finder_spec.rb create mode 100644 vim/bundle/Command-T/spec/command-t/finder/file_finder_spec.rb create mode 100644 vim/bundle/Command-T/spec/command-t/match_spec.rb create mode 100644 vim/bundle/Command-T/spec/command-t/matcher_spec.rb create mode 100644 vim/bundle/Command-T/spec/command-t/scanner/buffer_scanner_spec.rb create mode 100644 vim/bundle/Command-T/spec/command-t/scanner/file_scanner_spec.rb create mode 100644 vim/bundle/Command-T/spec/spec_helper.rb create mode 100644 vim/bundle/Command-T/spec/vim_formatter.rb delete mode 100644 vim/bundle/vim-ruby-debugger/.gitattributes delete mode 100644 vim/bundle/vim-ruby-debugger/.gitignore delete mode 100644 vim/bundle/vim-ruby-debugger/README.md delete mode 100644 vim/bundle/vim-ruby-debugger/autoload/ruby_debugger.vim delete mode 100644 vim/bundle/vim-ruby-debugger/bin/ruby_debugger.rb delete mode 100644 vim/bundle/vim-ruby-debugger/doc/ruby_debugger.txt delete mode 100644 vim/bundle/vim-ruby-debugger/plugin/ruby_debugger.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/additionals/autoload/ruby_debugger.vim delete mode 100755 vim/bundle/vim-ruby-debugger/src/additionals/bin/socket delete mode 100644 vim/bundle/vim-ruby-debugger/src/collector.rb delete mode 100755 vim/bundle/vim-ruby-debugger/src/notifier delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/after.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/before.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/breakpoint.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/commands.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/common.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/exception.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/frame.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/init.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/logger.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/public.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/queue.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/server.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/var.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/var_child.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/var_parent.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/window.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/window_breakpoints.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/window_frames.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger/window_variables.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger_autoload_plan.txt delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_debugger_plugin_plan.txt delete mode 100644 vim/bundle/vim-ruby-debugger/src/ruby_test_plan.txt delete mode 100644 vim/bundle/vim-ruby-debugger/src/socket.c delete mode 100644 vim/bundle/vim-ruby-debugger/src/tests/breakpoint.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/tests/command.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/tests/exceptions.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/tests/frames.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/tests/framework.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/tests/mock.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/tests/server.vim delete mode 100644 vim/bundle/vim-ruby-debugger/src/tests/variables.vim create mode 100644 vim/bundle/vim-rvm/.gitignore create mode 100644 vim/bundle/vim-rvm/README.markdown create mode 100644 vim/bundle/vim-rvm/doc/rvm.txt create mode 100644 vim/bundle/vim-rvm/plugin/rvm.vim diff --git a/vim/bundle/Command-T/.gitignore b/vim/bundle/Command-T/.gitignore new file mode 100644 index 0000000..6b2949a --- /dev/null +++ b/vim/bundle/Command-T/.gitignore @@ -0,0 +1,3 @@ +.release-notes.txt +command-t.recipe +/.bundle diff --git a/vim/bundle/Command-T/.gitmodules b/vim/bundle/Command-T/.gitmodules new file mode 100644 index 0000000..1a2bcf8 --- /dev/null +++ b/vim/bundle/Command-T/.gitmodules @@ -0,0 +1,6 @@ +[submodule "vendor/vimball"] + path = vendor/vimball + url = git://github.com/tomtom/vimball.rb.git +[submodule "vendor/vimscriptuploader"] + path = vendor/vimscriptuploader + url = git://github.com/tomtom/vimscriptuploader.rb.git diff --git a/vim/bundle/Command-T/.mailmap b/vim/bundle/Command-T/.mailmap new file mode 100644 index 0000000..63bc509 --- /dev/null +++ b/vim/bundle/Command-T/.mailmap @@ -0,0 +1,5 @@ +Nicolas Alpi Spyou +Noon Silk Noon Silk +Noon Silk Noon Silk +Sung Pae guns +Sung Pae guns diff --git a/vim/bundle/Command-T/.rspec b/vim/bundle/Command-T/.rspec new file mode 100644 index 0000000..53607ea --- /dev/null +++ b/vim/bundle/Command-T/.rspec @@ -0,0 +1 @@ +--colour diff --git a/vim/bundle/Command-T/.vim_org.yml b/vim/bundle/Command-T/.vim_org.yml new file mode 100644 index 0000000..20670d5 --- /dev/null +++ b/vim/bundle/Command-T/.vim_org.yml @@ -0,0 +1,2 @@ +--- {} + diff --git a/vim/bundle/Command-T/Gemfile b/vim/bundle/Command-T/Gemfile new file mode 100644 index 0000000..cb3c6b8 --- /dev/null +++ b/vim/bundle/Command-T/Gemfile @@ -0,0 +1,5 @@ +source :rubygems +gem 'mechanize' +gem 'rake' +gem 'rr' +gem 'rspec', '>= 2.0.0.rc' diff --git a/vim/bundle/Command-T/Gemfile.lock b/vim/bundle/Command-T/Gemfile.lock new file mode 100644 index 0000000..93bce22 --- /dev/null +++ b/vim/bundle/Command-T/Gemfile.lock @@ -0,0 +1,26 @@ +GEM + remote: http://rubygems.org/ + specs: + diff-lcs (1.1.2) + mechanize (1.0.0) + nokogiri (>= 1.2.1) + nokogiri (1.4.4) + rake (0.8.7) + rr (1.0.2) + rspec (2.5.0) + rspec-core (~> 2.5.0) + rspec-expectations (~> 2.5.0) + rspec-mocks (~> 2.5.0) + rspec-core (2.5.1) + rspec-expectations (2.5.0) + diff-lcs (~> 1.1.2) + rspec-mocks (2.5.0) + +PLATFORMS + ruby + +DEPENDENCIES + mechanize + rake + rr + rspec (>= 2.0.0.rc) diff --git a/vim/bundle/Command-T/LICENSE b/vim/bundle/Command-T/LICENSE new file mode 100644 index 0000000..5fd0feb --- /dev/null +++ b/vim/bundle/Command-T/LICENSE @@ -0,0 +1,22 @@ +Copyright 2010-2012 Wincent Colaiuta. 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. diff --git a/vim/bundle/Command-T/Makefile b/vim/bundle/Command-T/Makefile new file mode 100644 index 0000000..4803a21 --- /dev/null +++ b/vim/bundle/Command-T/Makefile @@ -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 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 diff --git a/vim/bundle/Command-T/README.txt b/vim/bundle/Command-T/README.txt new file mode 120000 index 0000000..b6d0b0b --- /dev/null +++ b/vim/bundle/Command-T/README.txt @@ -0,0 +1 @@ +doc/command-t.txt \ No newline at end of file diff --git a/vim/bundle/Command-T/Rakefile b/vim/bundle/Command-T/Rakefile new file mode 100644 index 0000000..82aa4d5 --- /dev/null +++ b/vim/bundle/Command-T/Rakefile @@ -0,0 +1,217 @@ +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 and 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 + bundle exec rake upload:all + rake archive + +Most of the Rake tasks run fine without Bundler, and in fact, we +don't want Bundler in the prerelease task because it will tamper +with the environment in a way that breaks multiruby. + +We use Bundler for the upload task because the www.vim.org +uploader uses Bundler to ensure that the Mechanize gem is available. + + END +end + +task :check_bundler do + unless ENV.has_key? 'BUNDLE_GEMFILE' + warn 'warning: Bundler is not loaded; try running with `bundle exec rake`' + 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 + +namespace :make do + desc 'Compile under all multiruby versions' + task :all do + system './compile-test.sh' + bail_on_failure + end +end + +namespace :spec do + desc 'Run specs under all multiruby versions' + task :all do + system './multi-spec.sh' + 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:all', 'spec:all', :vimball, :check_tag] + +namespace :upload do + desc 'Upload current vimball to Amazon S3' + task :s3 => :vimball do + sh 'aws put ' + + "s3.wincent.com/command-t/releases/command-t-#{version}.vba " + + "command-t-#{version}.vba" + sh 'aws put ' + + "s3.wincent.com/command-t/releases/command-t-#{version}.vba?acl " + + '--public' + end + + desc 'Upload current vimball to www.vim.org' + task :vim => [:check_bundler, :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 'Add current vimball to releases branch' +task :archive => :vimball do + v = version # store version before switching branches + sh 'git stash && ' + + 'git checkout releases && ' + + "git add command-t-#{v}.vba && " + + "git commit -s -m 'Add #{v} release vimball' && " + + 'git checkout @{-1} && ' + + 'git stash pop || true' +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 diff --git a/vim/bundle/Command-T/bin/.gitignore b/vim/bundle/Command-T/bin/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/vim/bundle/Command-T/bin/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/vim/bundle/Command-T/command-t.gemspec b/vim/bundle/Command-T/command-t.gemspec new file mode 100644 index 0000000..bb78158 --- /dev/null +++ b/vim/bundle/Command-T/command-t.gemspec @@ -0,0 +1,37 @@ +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 = ["Wincent Colaiuta"] + s.date = "2011-01-05" + s.email = "win@wincent.com" + + 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.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 diff --git a/vim/bundle/Command-T/compile-test.sh b/vim/bundle/Command-T/compile-test.sh new file mode 100755 index 0000000..6f94f6a --- /dev/null +++ b/vim/bundle/Command-T/compile-test.sh @@ -0,0 +1,10 @@ +#!/bin/sh -e +cd ruby/command-t +for RUBY_VERSION in $(ls ~/.multiruby/install); do + echo "$RUBY_VERSION: building" + export PATH=~/.multiruby/install/$RUBY_VERSION/bin:$PATH + ruby extconf.rb + make clean + make + echo "$RUBY_VERSION: finished" +done diff --git a/vim/bundle/Command-T/doc/.gitignore b/vim/bundle/Command-T/doc/.gitignore new file mode 100644 index 0000000..6e92f57 --- /dev/null +++ b/vim/bundle/Command-T/doc/.gitignore @@ -0,0 +1 @@ +tags diff --git a/vim/bundle/Command-T/doc/command-t.txt b/vim/bundle/Command-T/doc/command-t.txt new file mode 100644 index 0000000..c22a740 --- /dev/null +++ b/vim/bundle/Command-T/doc/command-t.txt @@ -0,0 +1,896 @@ +*command-t.txt* Command-T plug-in for Vim *command-t* + +CONTENTS *command-t-contents* + + 1. Introduction |command-t-intro| + 2. Requirements |command-t-requirements| + 3. Installation |command-t-installation| + 3. Managing using Pathogen |command-t-pathogen| + 4. Trouble-shooting |command-t-trouble-shooting| + 5. Usage |command-t-usage| + 6. Commands |command-t-commands| + 7. Mappings |command-t-mappings| + 8. Options |command-t-options| + 9. Authors |command-t-authors| +10. Development |command-t-development| +11. Website |command-t-website| +12. Donations |command-t-donations| +13. License |command-t-license| +14. History |command-t-history| + + +INTRODUCTION *command-t-intro* + +The Command-T plug-in provides an extremely fast, intuitive mechanism for +opening files and buffers with a minimal number of keystrokes. It's named +"Command-T" because it is inspired by the "Go to File" window bound to +Command-T in TextMate. + +Files are selected by typing characters that appear in their paths, and are +ordered by an algorithm which knows that characters that appear in certain +locations (for example, immediately after a path separator) should be given +more weight. + +To search efficiently, especially in large projects, you should adopt a +"path-centric" rather than a "filename-centric" mentality. That is you should +think more about where the desired file is found rather than what it is +called. This means narrowing your search down by including some characters +from the upper path components rather than just entering characters from the +filename itself. + +Screencasts demonstrating the plug-in can be viewed at: + + https://wincent.com/products/command-t + + +REQUIREMENTS *command-t-requirements* + +The plug-in requires Vim compiled with Ruby support, a compatible Ruby +installation at the operating system level, and a C compiler to build +the Ruby extension. + + +1. Vim compiled with Ruby support + +You can check for Ruby support by launching Vim with the --version switch: + + vim --version + +If "+ruby" appears in the version information then your version of Vim has +Ruby support. + +Another way to check is to simply try using the :ruby command from within Vim +itself: + + :ruby 1 + +If your Vim lacks support you'll see an error message like this: + + E319: Sorry, the command is not available in this version + +The version of Vim distributed with Mac OS X does not include Ruby support, +while MacVim does; it is available from: + + http://github.com/b4winckler/macvim/downloads + +For Windows users, the Vim 7.2 executable available from www.vim.org does +include Ruby support, and is recommended over version 7.3 (which links against +Ruby 1.9, but apparently has some bugs that need to be resolved). + + +2. Ruby + +In addition to having Ruby support in Vim, your system itself must have a +compatible Ruby install. "Compatible" means the same version as Vim itself +links against. If you use a different version then Command-T is unlikely +to work (see TROUBLE-SHOOTING below). + +On Mac OS X Snow Leopard, the system comes with Ruby 1.8.7 and all recent +versions of MacVim (the 7.2 snapshots and 7.3) are linked against it. + +On Linux and similar platforms, the linked version of Ruby will depend on +your distribution. You can usually find this out by examining the +compilation and linking flags displayed by the |:version| command in Vim, and +by looking at the output of: + + :ruby puts RUBY_VERSION + +A suitable Ruby environment for Windows can be installed using the Ruby +1.8.7-p299 RubyInstaller available at: + + http://rubyinstaller.org/downloads/archives + +If using RubyInstaller be sure to download the installer executable, not the +7-zip archive. When installing mark the checkbox "Add Ruby executables to your +PATH" so that Vim can find them. + + +3. C compiler + +Part of Command-T is implemented in C as a Ruby extension for speed, allowing +it to work responsively even on directory hierarchies containing enormous +numbers of files. As such, a C compiler is required in order to build the +extension and complete the installation. + +On Mac OS X, this can be obtained by installing the Xcode Tools that come on +the Mac OS X install disc. + +On Windows, the RubyInstaller Development Kit can be used to conveniently +install the necessary tool chain: + + http://rubyinstaller.org/downloads/archives + +At the time of writing, the appropriate development kit for use with Ruby +1.8.7 is DevKit-3.4.5r3-20091110. + +To use the Development Kit extract the archive contents to your C:\Ruby +folder. + + +INSTALLATION *command-t-installation* + +Command-T is distributed as a "vimball" which means that it can be installed +by opening it in Vim and then sourcing it: + + :e command-t.vba + :so % + +The files will be installed in your |'runtimepath'|. To check where this is +you can issue: + + :echo &rtp + +The C extension must then be built, which can be done from the shell. If you +use a typical |'runtimepath'| then the files were installed inside ~/.vim and +you can build the extension with: + + cd ~/.vim/ruby/command-t + ruby extconf.rb + make + +Note: If you are an RVM or rbenv user, you must perform the build using the +same version of Ruby that Vim itself is linked against. This will often be the +system Ruby, which can be selected before issuing the "make" command with one +of the following commands: + + rvm use system + rbenv local system + +Note: Make sure you compile targeting the same architecture Vim was built for. +For instance, MacVim binaries are built for i386, but sometimes GCC compiles +for x86_64. First you have to check the platfom Vim was built for: + + vim --version + ... + Compilation: gcc ... -arch i386 ... + ... + +and make sure you use the correct ARCHFLAGS during compilation: + + export ARCHFLAGS="-arch i386" + make + + +MANAGING USING PATHOGEN *command-t-pathogen* + +Pathogen is a plugin that allows you to maintain plugin installations in +separate, isolated subdirectories under the "bundle" directory in your +|'runtimepath'|. The following examples assume that you already have +Pathogen installed and configured, and that you are installing into +~/.vim/bundle. For more information about Pathogen, see: + + http://www.vim.org/scripts/script.php?script_id=2332 + +If you manage your entire ~/.vim folder using Git then you can add the +Command-T repository as a submodule: + + cd ~/.vim + git submodule add git://git.wincent.com/command-t.git bundle/command-t + git submodule init + +Or if you just wish to do a simple clone instead of using submodules: + + cd ~/.vim + git clone git://git.wincent.com/command-t.git bundle/command-t + +Once you have a local copy of the repository you can update it at any time +with: + + cd ~/.vim/bundle/command-t + git pull + +Or you can switch to a specific release with: + + cd ~/.vim/bundle/command-t + git checkout 0.8b + +After installing or updating you must build the extension: + + cd ~/.vim/bundle/command-t + bundle install + rake make + +While the Vimball installation automatically generates the help tags, under +Pathogen it is necessary to do so explicitly from inside Vim: + + :call pathogen#helptags() + + +TROUBLE-SHOOTING *command-t-trouble-shooting* + +Most installation problems are caused by a mismatch between the version of +Ruby on the host operating system, and the version of Ruby that Vim itself +linked against at compile time. For example, if one is 32-bit and the other is +64-bit, or one is from the Ruby 1.9 series and the other is from the 1.8 +series, then the plug-in is not likely to work. + +As such, on Mac OS X, I recommend using the standard Ruby that comes with the +system (currently 1.8.7) along with the latest version of MacVim (currently +version 7.3). If you wish to use custom builds of Ruby or of MacVim (not +recommmended) then you will have to take extra care to ensure that the exact +same Ruby environment is in effect when building Ruby, Vim and the Command-T +extension. + +For Windows, the following combination is known to work: + + - Vim 7.2 from http://www.vim.org/download.php: + ftp://ftp.vim.org/pub/vim/pc/gvim72.exe + - Ruby 1.8.7-p299 from http://rubyinstaller.org/downloads/archives: + http://rubyforge.org/frs/download.php/71492/rubyinstaller-1.8.7-p299.exe + - DevKit 3.4.5r3-20091110 from http://rubyinstaller.org/downloads/archives: + http://rubyforge.org/frs/download.php/66888/devkit-3.4.5r3-20091110.7z + +If a problem occurs the first thing you should do is inspect the output of: + + ruby extconf.rb + make + +During the installation, and: + + vim --version + +And compare the compilation and linker flags that were passed to the +extension and to Vim itself when they were built. If the Ruby-related +flags or architecture flags are different then it is likely that something +has changed in your Ruby environment and the extension may not work until +you eliminate the discrepancy. + + +USAGE *command-t-usage* + +Bring up the Command-T file window by typing: + + t + +This mapping is set up automatically for you, provided you do not already have +a mapping for t or |:CommandT|. You can also bring up the file window +by issuing the command: + + :CommandT + +A prompt will appear at the bottom of the screen along with a file window +showing all of the files in the current directory (as returned by the +|:pwd| command). + +For the most efficient file navigation within a project it's recommended that +you |:cd| into the root directory of your project when starting to work on it. +If you wish to open a file from outside of the project folder you can pass in +an optional path argument (relative or absolute) to |:CommandT|: + + :CommandT ../path/to/other/files + +Type letters in the prompt to narrow down the selection, showing only the +files whose paths contain those letters in the specified order. Letters do not +need to appear consecutively in a path in order for it to be classified as a +match. + +Once the desired file has been selected it can be opened by pressing . +(By default files are opened in the current window, but there are other +mappings that you can use to open in a vertical or horizontal split, or in +a new tab.) Note that if you have |'nohidden'| set and there are unsaved +changes in the current window when you press then opening in the current +window would fail; in this case Command-T will open the file in a new split. + +The following mappings are active when the prompt has focus: + + delete the character to the left of the cursor + delete the character at the cursor + move the cursor one character to the left + move the cursor one character to the left + move the cursor one character to the right + move the cursor one character to the right + move the cursor to the start (left) + move the cursor to the end (right) + clear the contents of the prompt + change focus to the file listing + +The following mappings are active when the file listing has focus: + + change focus to the prompt + +The following mappings are active when either the prompt or the file listing +has focus: + + open the selected file + open the selected file in a new split window + open the selected file in a new split window + open the selected file in a new vertical split window + open the selected file in a new tab + select next file in the file listing + select next file in the file listing + select next file in the file listing + select previous file in the file listing + select previous file in the file listing + select previous file in the file listing + flush the cache (see |:CommandTFlush| for details) + cancel (dismisses file listing) + +The following is also available on terminals which support it: + + cancel (dismisses file listing) + +Note that the default mappings can be overriden by setting options in your +~/.vimrc file (see the OPTIONS section for a full list of available options). + +In addition, when the file listing has focus, typing a character will cause +the selection to jump to the first path which begins with that character. +Typing multiple characters consecutively can be used to distinguish between +paths which begin with the same prefix. + + +COMMANDS *command-t-commands* + + *:CommandT* +|:CommandT| Brings up the Command-T file window, starting in the + current working directory as returned by the|:pwd| + command. + + *:CommandTBuffer* +|:CommandTBuffer|Brings up the Command-T buffer window. + This works exactly like the standard file window, + except that the selection is limited to files that + you already have open in buffers. + + *:CommandTJumps* +|:CommandTJump| Brings up the Command-T jumplist window. + This works exactly like the standard file window, + except that the selection is limited to files that + you already have in the jumplist. Note that jumps + can persist across Vim sessions (see Vim's |jumplist| + documentation for more info). + + *:CommandTTag* +|:CommandTTag| Brings up the Command-T window tags window, which can + be used to select from the tags, if any, returned by + Vim's |taglist()| function. See Vim's |tag| documentation + for general info on tags. + + *:CommandTFlush* +|:CommandTFlush|Instructs the plug-in to flush its path cache, causing + the directory to be rescanned for new or deleted paths + the next time the file window is shown (pressing when + a match listing is visible flushes the cache immediately; this + mapping is configurable via the |g:CommandTRefreshMap| + setting). In addition, all configuration settings are + re-evaluated, causing any changes made to settings via the + |:let| command to be picked up. + + +MAPPINGS *command-t-mappings* + +By default Command-T comes with only two mappings: + + t bring up the Command-T file window + b bring up the Command-T buffer window + +However, Command-T won't overwrite a pre-existing mapping so if you prefer +to define different mappings use lines like these in your ~/.vimrc: + + nnoremap t :CommandT + nnoremap b :CommandTBuffer + +Replacing "t" or "b" with your mapping of choice. + +Note that in the case of MacVim you actually can map to Command-T (written +as in Vim) in your ~/.gvimrc file if you first unmap the existing menu +binding of Command-T to "New Tab": + + if has("gui_macvim") + macmenu &File.New\ Tab key= + map :CommandT + endif + +When the Command-T window is active a number of other additional mappings +become available for doing things like moving between and selecting matches. +These are fully described above in the USAGE section, and settings for +overriding the mappings are listed below under OPTIONS. + + +OPTIONS *command-t-options* + +A number of options may be set in your ~/.vimrc to influence the behaviour of +the plug-in. To set an option, you include a line like this in your ~/.vimrc: + + let g:CommandTMaxFiles=20000 + +To have Command-T pick up new settings immediately (that is, without having +to restart Vim) you can issue the |:CommandTFlush| command after making +changes via |:let|. + +Following is a list of all available options: + + *g:CommandTMaxFiles* + |g:CommandTMaxFiles| number (default 10000) + + The maximum number of files that will be considered when scanning the + current directory. Upon reaching this number scanning stops. This + limit applies only to file listings and is ignored for buffer + listings. + + *g:CommandTMaxDepth* + |g:CommandTMaxDepth| number (default 15) + + The maximum depth (levels of recursion) to be explored when scanning the + current directory. Any directories at levels beyond this depth will be + skipped. + + *g:CommandTMaxCachedDirectories* + |g:CommandTMaxCachedDirectories| number (default 1) + + The maximum number of directories whose contents should be cached when + recursively scanning. With the default value of 1, each time you change + directories the cache will be emptied and Command-T will have to + rescan. Higher values will make Command-T hold more directories in the + cache, bringing performance at the cost of memory usage. If set to 0, + there is no limit on the number of cached directories. + + *g:CommandTMaxHeight* + |g:CommandTMaxHeight| number (default: 0) + + The maximum height in lines the match window is allowed to expand to. + If set to 0, the window will occupy as much of the available space as + needed to show matching entries. + + *g:CommandTMinHeight* + |g:CommandTMinHeight| number (default: 0) + + The minimum height in lines the match window is allowed to shrink to. + If set to 0, will default to a single line. If set above the max height, + will default to |g:CommandTMaxHeight|. + + *g:CommandTAlwaysShowDotFiles* + |g:CommandTAlwaysShowDotFiles| boolean (default: 0) + + When showing the file listing Command-T will by default show dot-files + only if the entered search string contains a dot that could cause a + dot-file to match. When set to a non-zero value, this setting instructs + Command-T to always include matching dot-files in the match list + regardless of whether the search string contains a dot. See also + |g:CommandTNeverShowDotFiles|. Note that this setting only influences + the file listing; the buffer listing treats dot-files like any other + file. + + *g:CommandTNeverShowDotFiles* + |g:CommandTNeverShowDotFiles| boolean (default: 0) + + In the file listing, Command-T will by default show dot-files if the + entered search string contains a dot that could cause a dot-file to + match. When set to a non-zero value, this setting instructs Command-T to + never show dot-files under any circumstances. Note that it is + contradictory to set both this setting and + |g:CommandTAlwaysShowDotFiles| to true, and if you do so Vim will suffer + from headaches, nervous twitches, and sudden mood swings. This setting + has no effect in buffer listings, where dot files are treated like any + other file. + + *g:CommandTScanDotDirectories* + |g:CommandTScanDotDirectories| boolean (default: 0) + + Normally Command-T will not recurse into "dot-directories" (directories + whose names begin with a dot) while performing its initial scan. Set + this setting to a non-zero value to override this behavior and recurse. + Note that this setting is completely independent of the + |g:CommandTAlwaysShowDotFiles| and |g:CommandTNeverShowDotFiles| + settings; those apply only to the selection and display of matches + (after scanning has been performed), whereas + |g:CommandTScanDotDirectories| affects the behaviour at scan-time. + + Note also that even with this setting off you can still use Command-T to + open files inside a "dot-directory" such as ~/.vim, but you have to use + the |:cd| command to change into that directory first. For example: + + :cd ~/.vim + :CommandT + + *g:CommandTMatchWindowAtTop* + |g:CommandTMatchWindowAtTop| boolean (default: 0) + + When this setting is off (the default) the match window will appear at + the bottom so as to keep it near to the prompt. Turning it on causes the + match window to appear at the top instead. This may be preferable if you + want the best match (usually the first one) to appear in a fixed location + on the screen rather than moving as the number of matches changes during + typing. + + *g:CommandTMatchWindowReverse* + |g:CommandTMatchWindowReverse| boolean (default: 0) + + When this setting is off (the default) the matches will appear from + top to bottom with the topmost being selected. Turning it on causes the + matches to be reversed so the best match is at the bottom and the + initially selected match is the bottom most. This may be preferable if + you want the best match to appear in a fixed location on the screen + but still be near the prompt at the bottom. + + *g:CommandTTagIncludeFilenames* + |g:CommandTTagIncludeFilenames| boolean (default: 0) + + When this setting is off (the default) the matches in the |:CommandTTag| + listing do not include filenames. + +As well as the basic options listed above, there are a number of settings that +can be used to override the default key mappings used by Command-T. For +example, to set as the mapping for cancelling (dismissing) the Command-T +window, you would add the following to your ~/.vimrc: + + let g:CommandTCancelMap='' + +Multiple, alternative mappings may be specified using list syntax: + + let g:CommandTCancelMap=['', ''] + +Following is a list of all map settings and their defaults: + + Setting Default mapping(s) + + *g:CommandTBackspaceMap* + |g:CommandTBackspaceMap| + + *g:CommandTDeleteMap* + |g:CommandTDeleteMap| + + *g:CommandTAcceptSelectionMap* + |g:CommandTAcceptSelectionMap| + + *g:CommandTAcceptSelectionSplitMap* + |g:CommandTAcceptSelectionSplitMap| + + + *g:CommandTAcceptSelectionTabMap* + |g:CommandTAcceptSelectionTabMap| + + *g:CommandTAcceptSelectionVSplitMap* + |g:CommandTAcceptSelectionVSplitMap| + + *g:CommandTToggleFocusMap* + |g:CommandTToggleFocusMap| + + *g:CommandTCancelMap* + |g:CommandTCancelMap| + (not on all terminals) + + *g:CommandTSelectNextMap* + |g:CommandTSelectNextMap| + + + + *g:CommandTSelectPrevMap* + |g:CommandTSelectPrevMap| + + + + *g:CommandTClearMap* + |g:CommandTClearMap| + + *g:CommandTRefreshMap* + |g:CommandTRefreshMap| + + *g:CommandTCursorLeftMap* + |g:CommandTCursorLeftMap| + + + *g:CommandTCursorRightMap* + |g:CommandTCursorRightMap| + + + *g:CommandTCursorEndMap* + |g:CommandTCursorEndMap| + + *g:CommandTCursorStartMap* + |g:CommandTCursorStartMap| + +In addition to the options provided by Command-T itself, some of Vim's own +settings can be used to control behavior: + + *command-t-wildignore* + |'wildignore'| string (default: '') + + Vim's |'wildignore'| setting is used to determine which files should be + excluded from listings. This is a comma-separated list of glob patterns. + It defaults to the empty string, but common settings include "*.o,*.obj" + (to exclude object files) or ".git,.svn" (to exclude SCM metadata + directories). For example: + + :set wildignore+=*.o,*.obj,.git + + A pattern such as "vendor/rails/**" would exclude all files and + subdirectories inside the "vendor/rails" directory (relative to + directory Command-T starts in). + + See the |'wildignore'| documentation for more information. + + +AUTHORS *command-t-authors* + +Command-T is written and maintained by Wincent Colaiuta . +Other contributors that have submitted patches include (in alphabetical +order): + + Anthony Panozzo Mike Lundy Steven Moazami + Daniel Hahler Nate Kane Sung Pae + Felix Tjandrawibawa Nicholas Alpi Thomas Pelletier + Gary Bernhardt Nadav Samet Victor Hugo Borja + Jeff Kreeftmeijer Noon Silk Woody Peterson + Lucas de Vries Rainux Luo Yan Pritzker + Marian Schubert Scott Bronson Zak Johnson + Matthew Todd Seth Fowler + +As this was the first Vim plug-in I had ever written I was heavily influenced +by the design of the LustyExplorer plug-in by Stephen Bach, which I understand +is one of the largest Ruby-based Vim plug-ins to date. + +While the Command-T codebase doesn't contain any code directly copied from +LustyExplorer, I did use it as a reference for answers to basic questions (like +"How do you do 'X' in a Ruby-based Vim plug-in?"), and also copied some basic +architectural decisions (like the division of the code into Prompt, Settings +and MatchWindow classes). + +LustyExplorer is available from: + + http://www.vim.org/scripts/script.php?script_id=1890 + + +DEVELOPMENT *command-t-development* + +Development in progress can be inspected via the project's Git web-based +repository browser at: + + https://wincent.com/repos/command-t + +the clone URL for which is: + + git://git.wincent.com/command-t.git + +Mirrors exist on GitHub and Gitorious; these are automatically updated once +per hour from the authoritative repository: + + https://github.com/wincent/command-t + https://gitorious.org/command-t/command-t + +Patches are welcome via the usual mechanisms (pull requests, email, posting to +the project issue tracker etc). + +As many users choose to track Command-T using Pathogen, which often means +running a version later than the last official release, the intention is that +the "master" branch should be kept in a stable and reliable state as much as +possible. + +Riskier changes are first cooked on the "next" branch for a period before +being merged into master. You can track this branch if you're feeling wild and +experimental, but note that the "next" branch may periodically be rewound +(force-updated) to keep it in sync with the "master" branch after each +official release. + + +WEBSITE *command-t-website* + +The official website for Command-T is: + + https://wincent.com/products/command-t + +The latest release will always be available from there. + +A copy of each release is also available from the official Vim scripts site +at: + + http://www.vim.org/scripts/script.php?script_id=3025 + +Bug reports should be submitted to the issue tracker at: + + https://wincent.com/issues + + +DONATIONS *command-t-donations* + +Command-T itself is free software released under the terms of the BSD license. +If you would like to support further development you can make a donation via +PayPal to win@wincent.com: + + https://wincent.com/products/command-t/donations + + +LICENSE *command-t-license* + +Copyright 2010-2012 Wincent Colaiuta. 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. + +HISTORY *command-t-history* + +1.4 (not yet released) + +- added |:CommandTTag| command (patches from Noon Silk) +- turn off |'colorcolumn'| and |'relativenumber'| in the match window (patch + from Jeff Kreeftmeijer) +- documentation update (patch from Nicholas Alpi) +- added |:CommandTMinHeight| option (patch from Nate Kane) +- highlight (by underlining) matched characters in the match listing (requires + Vim to have been compiled with the +conceal feature, which is available in + Vim 7.3 or later; patch from Steven Moazami) +- added the ability to flush the cache while the match window is open using + + +1.3.1 (18 December 2011) + +- fix jumplist navigation under Ruby 1.9.x (patch from Woody Peterson) + +1.3 (27 November 2011) + +- added the option to maintain multiple caches when changing among + directories; see the accompanying |g:CommandTMaxCachedDirectories| setting +- added the ability to navigate using the Vim jumplist (patch from Marian + Schubert) + +1.2.1 (30 April 2011) + +- Remove duplicate copy of the documentation that was causing "Duplicate tag" + errors +- Mitigate issue with distracting blinking cursor in non-GUI versions of Vim + (patch from Steven Moazami) + +1.2 (30 April 2011) + +- added |g:CommandTMatchWindowReverse| option, to reverse the order of items + in the match listing (patch from Steven Moazami) + +1.1b2 (26 March 2011) + +- fix a glitch in the release process; the plugin itself is unchanged since + 1.1b + +1.1b (26 March 2011) + +- add |:CommandTBuffer| command for quickly selecting among open buffers + +1.0.1 (5 January 2011) + +- work around bug when mapping |:CommandTFlush|, wherein the default mapping + for |:CommandT| would not be set up +- clean up when leaving the Command-T buffer via unexpected means (such as + with or similar) + +1.0 (26 November 2010) + +- make relative path simplification work on Windows + +1.0b (5 November 2010) + +- work around platform-specific Vim 7.3 bug seen by some users (wherein + Vim always falsely reports to Ruby that the buffer numbers is 0) +- re-use the buffer that is used to show the match listing, rather than + throwing it away and recreating it each time Command-T is shown; this + stops the buffer numbers from creeping up needlessly + +0.9 (8 October 2010) + +- use relative paths when opening files inside the current working directory + in order to keep buffer listings as brief as possible (patch from Matthew + Todd) + +0.8.1 (14 September 2010) + +- fix mapping issues for users who have set |'notimeout'| (patch from Sung + Pae) + +0.8 (19 August 2010) + +- overrides for the default mappings can now be lists of strings, allowing + multiple mappings to be defined for any given action +- t mapping only set up if no other map for |:CommandT| exists + (patch from Scott Bronson) +- prevent folds from appearing in the match listing +- tweaks to avoid the likelihood of "Not enough room" errors when trying to + open files +- watch out for "nil" windows when restoring window dimensions +- optimizations (avoid some repeated downcasing) +- move all Ruby files under the "command-t" subdirectory and avoid polluting + the "Vim" module namespace + +0.8b (11 July 2010) + +- large overhaul of the scoring algorithm to make the ordering of returned + results more intuitive; given the scope of the changes and room for + optimization of the new algorithm, this release is labelled as "beta" + +0.7 (10 June 2010) + +- handle more |'wildignore'| patterns by delegating to Vim's own |expand()| + function; with this change it is now viable to exclude patterns such as + 'vendor/rails/**' in addition to filename-only patterns like '*.o' and + '.git' (patch from Mike Lundy) +- always sort results alphabetically for empty search strings; this eliminates + filesystem-specific variations (patch from Mike Lundy) + +0.6 (28 April 2010) + +- |:CommandT| now accepts an optional parameter to specify the starting + directory, temporarily overriding the usual default of Vim's |:pwd| +- fix truncated paths when operating from root directory + +0.5.1 (11 April 2010) + +- fix for Ruby 1.9 compatibility regression introduced in 0.5 +- documentation enhancements, specifically targetted at Windows users + +0.5 (3 April 2010) + +- |:CommandTFlush| now re-evaluates settings, allowing changes made via |let| + to be picked up without having to restart Vim +- fix premature abort when scanning very deep directory hierarchies +- remove broken || key mapping on vt100 and xterm terminals +- provide settings for overriding default mappings +- minor performance optimization + +0.4 (27 March 2010) + +- add |g:CommandTMatchWindowAtTop| setting (patch from Zak Johnson) +- documentation fixes and enhancements +- internal refactoring and simplification + +0.3 (24 March 2010) + +- add |g:CommandTMaxHeight| setting for controlling the maximum height of the + match window (patch from Lucas de Vries) +- fix bug where |'list'| setting might be inappropriately set after dismissing + Command-T +- compatibility fix for different behaviour of "autoload" under Ruby 1.9.1 +- avoid "highlight group not found" warning when run under a version of Vim + that does not have syntax highlighting support +- open in split when opening normally would fail due to |'hidden'| and + |'modified'| values + +0.2 (23 March 2010) + +- compatibility fixes for compilation under Ruby 1.9 series +- compatibility fixes for compilation under Ruby 1.8.5 +- compatibility fixes for Windows and other non-UNIX platforms +- suppress "mapping already exists" message if t mapping is already + defined when plug-in is loaded +- exclude paths based on |'wildignore'| setting rather than a hardcoded + regular expression + +0.1 (22 March 2010) + +- initial public release + +------------------------------------------------------------------------------ +vim:tw=78:ft=help: diff --git a/vim/bundle/Command-T/fixtures/bar/abc b/vim/bundle/Command-T/fixtures/bar/abc new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/vim/bundle/Command-T/fixtures/bar/abc @@ -0,0 +1 @@ +. diff --git a/vim/bundle/Command-T/fixtures/bar/xyz b/vim/bundle/Command-T/fixtures/bar/xyz new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/vim/bundle/Command-T/fixtures/bar/xyz @@ -0,0 +1 @@ +. diff --git a/vim/bundle/Command-T/fixtures/baz b/vim/bundle/Command-T/fixtures/baz new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/vim/bundle/Command-T/fixtures/baz @@ -0,0 +1 @@ +. diff --git a/vim/bundle/Command-T/fixtures/bing b/vim/bundle/Command-T/fixtures/bing new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/vim/bundle/Command-T/fixtures/bing @@ -0,0 +1 @@ +. diff --git a/vim/bundle/Command-T/fixtures/foo/alpha/t1 b/vim/bundle/Command-T/fixtures/foo/alpha/t1 new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/vim/bundle/Command-T/fixtures/foo/alpha/t1 @@ -0,0 +1 @@ +. diff --git a/vim/bundle/Command-T/fixtures/foo/alpha/t2 b/vim/bundle/Command-T/fixtures/foo/alpha/t2 new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/vim/bundle/Command-T/fixtures/foo/alpha/t2 @@ -0,0 +1 @@ +. diff --git a/vim/bundle/Command-T/fixtures/foo/beta b/vim/bundle/Command-T/fixtures/foo/beta new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/vim/bundle/Command-T/fixtures/foo/beta @@ -0,0 +1 @@ +. diff --git a/vim/bundle/Command-T/multi-spec.sh b/vim/bundle/Command-T/multi-spec.sh new file mode 100755 index 0000000..843c2ee --- /dev/null +++ b/vim/bundle/Command-T/multi-spec.sh @@ -0,0 +1,25 @@ +#!/bin/sh -e + +function build_quietly() +{ + (bundle install > /dev/null && + cd ruby/command-t && + ruby extconf.rb > /dev/null && + make clean > /dev/null && + make > /dev/null) +} + +OLD_PATH=$PATH +for RUBY_VERSION in $(ls ~/.multiruby/install); do + echo "$RUBY_VERSION: building" + export PATH=~/.multiruby/install/$RUBY_VERSION/bin:$OLD_PATH + build_quietly + echo "$RUBY_VERSION: running spec suite" + bundle exec rspec spec + echo "$RUBY_VERSION: finished" +done + +# put things back the way we found them +export PATH=$OLD_PATH +echo "Restoring: $(ruby -v)" +build_quietly diff --git a/vim/bundle/Command-T/plugin/command-t.vim b/vim/bundle/Command-T/plugin/command-t.vim new file mode 100644 index 0000000..68cac9e --- /dev/null +++ b/vim/bundle/Command-T/plugin/command-t.vim @@ -0,0 +1,186 @@ +" command-t.vim +" Copyright 2010-2012 Wincent Colaiuta. 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. + +if exists("g:command_t_loaded") || &cp + finish +endif +let g:command_t_loaded = 1 + +command CommandTBuffer call CommandTShowBufferFinder() +command CommandTJump call CommandTShowJumpFinder() +command CommandTTag call CommandTShowTagFinder() +command -nargs=? -complete=dir CommandT call CommandTShowFileFinder() +command CommandTFlush call CommandTFlush() + +if !hasmapto(':CommandT') + silent! nnoremap t :CommandT +endif + +if !hasmapto(':CommandTBuffer') + silent! nnoremap b :CommandTBuffer +endif + +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 s:CommandTShowBufferFinder() + if has('ruby') + ruby $command_t.show_buffer_finder + else + call s:CommandTRubyWarning() + endif +endfunction + +function s:CommandTShowFileFinder(arg) + if has('ruby') + ruby $command_t.show_file_finder + else + call s:CommandTRubyWarning() + endif +endfunction + +function s:CommandTShowJumpFinder() + if has('ruby') + ruby $command_t.show_jump_finder + else + call s:CommandTRubyWarning() + endif +endfunction + +function s:CommandTShowTagFinder() + if has('ruby') + ruby $command_t.show_tag_finder + else + call s:CommandTRubyWarning() + endif +endfunction + +function s:CommandTFlush() + if has('ruby') + ruby $command_t.flush + else + call s:CommandTRubyWarning() + endif +endfunction + +if !has('ruby') + finish +endif + +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 => 'tabe' +endfunction + +function CommandTAcceptSelectionSplit() + ruby $command_t.accept_selection :command => 'sp' +endfunction + +function CommandTAcceptSelectionVSplit() + ruby $command_t.accept_selection :command => 'vs' +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 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 + +ruby << EOF + # require Ruby files + begin + # prepare controller + require 'command-t/vim' + require 'command-t/controller' + $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) and 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 + require 'command-t/stub' + $command_t = CommandT::Stub.new + end +EOF diff --git a/vim/bundle/Command-T/ruby/command-t/.gitignore b/vim/bundle/Command-T/ruby/command-t/.gitignore new file mode 100644 index 0000000..c98bad5 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/.gitignore @@ -0,0 +1,6 @@ +Makefile +*.o +*.log +ext.* +!ext.c +!ext.h diff --git a/vim/bundle/Command-T/ruby/command-t/controller.rb b/vim/bundle/Command-T/ruby/command-t/controller.rb new file mode 100644 index 0000000..365f802 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/controller.rb @@ -0,0 +1,357 @@ +# Copyright 2010-2012 Wincent Colaiuta. 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. + +require 'command-t/finder/buffer_finder' +require 'command-t/finder/jump_finder' +require 'command-t/finder/file_finder' +require 'command-t/finder/tag_finder' +require 'command-t/match_window' +require 'command-t/prompt' +require 'command-t/vim/path_utilities' + +module CommandT + class Controller + include VIM::PathUtilities + + 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_tag_finder + @path = VIM::pwd + @active_finder = tag_finder + show + end + + def show_file_finder + # optional parameter will be desired starting directory, or "" + @path = File.expand_path(::VIM::evaluate('a:arg'), VIM::pwd) + @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.close + 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 + + 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 + list_matches + else + @match_window.find key + end + end + + def backspace + if @focus == @prompt + @prompt.backspace! + list_matches + end + end + + def delete + if @focus == @prompt + @prompt.delete! + list_matches + 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 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 + + private + + def show + @initial_window = $curwin + @initial_buffer = $curbuf + @match_window = MatchWindow.new \ + :prompt => @prompt, + :match_window_at_top => get_bool('g:CommandTMatchWindowAtTop'), + :match_window_reverse => get_bool('g:CommandTMatchWindowReverse'), + :min_height => min_height + @focus = @prompt + @prompt.focus + register_for_key_presses + clear # clears prompt and lists matches + end + + def max_height + @max_height ||= get_number('g:CommandTMaxHeight') || 0 + end + + def min_height + @min_height ||= begin + min_height = get_number('g:CommandTMinHeight') || 0 + min_height = max_height if max_height != 0 && min_height > max_height + min_height + end + end + + def get_number name + VIM::exists?(name) ? ::VIM::evaluate("#{name}").to_i : nil + end + + def get_bool name + VIM::exists?(name) ? ::VIM::evaluate("#{name}").to_i != 0 : nil + end + + def get_string name + VIM::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 VIM::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 + + # 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 default_open_command + if !get_bool('&hidden') && get_bool('&modified') + 'sp' + else + 'e' + 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 + ensure_appropriate_window_selection + + @active_finder.open_selection command, selection, options + end + + def map key, function, param = nil + ::VIM::command "noremap #{key} " \ + ":call CommandT#{function}(#{param})" + 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 "", 'HandleKey', b + end + + # "special" keys (overridable by settings) + { + 'AcceptSelection' => '', + 'AcceptSelectionSplit' => ['', ''], + 'AcceptSelectionTab' => '', + 'AcceptSelectionVSplit' => '', + 'Backspace' => '', + 'Cancel' => ['', ''], + 'Clear' => '', + 'CursorEnd' => '', + 'CursorLeft' => ['', ''], + 'CursorRight' => ['', ''], + 'CursorStart' => '', + 'Delete' => '', + 'Refresh' => '', + 'SelectNext' => ['', '', ''], + 'SelectPrev' => ['', '', ''], + 'ToggleFocus' => '', + }.each do |key, value| + if override = 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 == '' && term =~ /\A(screen|xterm|vt100)/ + map mapping, key + end + end + end + end + end + + # Returns the desired maximum number of matches, based on available + # vertical space and the g:CommandTMaxHeight option. + def match_limit + limit = VIM::Screen.lines - 5 + limit = 1 if limit < 0 + limit = [limit, max_height].min if max_height > 0 + limit + end + + def list_matches + matches = @active_finder.sorted_matches_for @prompt.abbrev, :limit => match_limit + @match_window.matches = matches + end + + def buffer_finder + @buffer_finder ||= CommandT::BufferFinder.new + end + + def file_finder + @file_finder ||= CommandT::FileFinder.new nil, + :max_depth => get_number('g:CommandTMaxDepth'), + :max_files => get_number('g:CommandTMaxFiles'), + :max_caches => get_number('g:CommandTMaxCachedDirectories'), + :always_show_dot_files => get_bool('g:CommandTAlwaysShowDotFiles'), + :never_show_dot_files => get_bool('g:CommandTNeverShowDotFiles'), + :scan_dot_directories => get_bool('g:CommandTScanDotDirectories') + end + + def jump_finder + @jump_finder ||= CommandT::JumpFinder.new + end + + def tag_finder + @tag_finder ||= CommandT::TagFinder.new \ + :include_filenames => get_bool('g:CommandTTagIncludeFilenames') + end + end # class Controller +end # module commandT diff --git a/vim/bundle/Command-T/ruby/command-t/depend b/vim/bundle/Command-T/ruby/command-t/depend new file mode 100644 index 0000000..bfa9552 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/depend @@ -0,0 +1,24 @@ +# Copyright 2010 Wincent Colaiuta. 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. + +CFLAGS += -std=c99 -Wall -Wextra -Wno-unused-parameter diff --git a/vim/bundle/Command-T/ruby/command-t/ext.c b/vim/bundle/Command-T/ruby/command-t/ext.c new file mode 100644 index 0000000..c5026cc --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/ext.c @@ -0,0 +1,65 @@ +// Copyright 2010 Wincent Colaiuta. 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. + +#include "match.h" +#include "matcher.h" + +VALUE mCommandT = 0; // module CommandT +VALUE cCommandTMatch = 0; // class CommandT::Match +VALUE cCommandTMatcher = 0; // class CommandT::Matcher + +VALUE CommandT_option_from_hash(const char *option, VALUE hash) +{ + if (NIL_P(hash)) + return Qnil; + VALUE 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::Match + cCommandTMatch = rb_define_class_under(mCommandT, "Match", rb_cObject); + + // methods + rb_define_method(cCommandTMatch, "initialize", CommandTMatch_initialize, -1); + rb_define_method(cCommandTMatch, "matches?", CommandTMatch_matches, 0); + rb_define_method(cCommandTMatch, "to_s", CommandTMatch_to_s, 0); + + // attributes + rb_define_attr(cCommandTMatch, "score", Qtrue, Qfalse); // reader: true, writer: false + + // class CommandT::Matcher + cCommandTMatcher = rb_define_class_under(mCommandT, "Matcher", rb_cObject); + + // methods + rb_define_method(cCommandTMatcher, "initialize", CommandTMatcher_initialize, -1); + rb_define_method(cCommandTMatcher, "sorted_matches_for", CommandTMatcher_sorted_matches_for, 2); + rb_define_method(cCommandTMatcher, "matches_for", CommandTMatcher_matches_for, 1); +} diff --git a/vim/bundle/Command-T/ruby/command-t/ext.h b/vim/bundle/Command-T/ruby/command-t/ext.h new file mode 100644 index 0000000..89ff076 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/ext.h @@ -0,0 +1,36 @@ +// Copyright 2010 Wincent Colaiuta. 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. + +#include + +extern VALUE mCommandT; // module CommandT +extern VALUE cCommandTMatch; // class CommandT::Match +extern VALUE cCommandTMatcher; // class CommandT::Matcher + +// 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) diff --git a/vim/bundle/Command-T/ruby/command-t/extconf.rb b/vim/bundle/Command-T/ruby/command-t/extconf.rb new file mode 100644 index 0000000..9d2bfb3 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/extconf.rb @@ -0,0 +1,34 @@ +# Copyright 2010 Wincent Colaiuta. 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. + +require 'mkmf' + +def missing item + puts "couldn't find #{item} (required)" + exit 1 +end + +RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC'] + +have_header('ruby.h') or missing('ruby.h') +create_makefile('ext') diff --git a/vim/bundle/Command-T/ruby/command-t/finder.rb b/vim/bundle/Command-T/ruby/command-t/finder.rb new file mode 100644 index 0000000..ff731a0 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/finder.rb @@ -0,0 +1,54 @@ +# Copyright 2010-2012 Wincent Colaiuta. 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. + +require 'command-t/ext' # CommandT::Matcher + +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 + include VIM::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 diff --git a/vim/bundle/Command-T/ruby/command-t/finder/buffer_finder.rb b/vim/bundle/Command-T/ruby/command-t/finder/buffer_finder.rb new file mode 100644 index 0000000..2319c24 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/finder/buffer_finder.rb @@ -0,0 +1,35 @@ +# Copyright 2010-2011 Wincent Colaiuta. 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. + +require 'command-t/ext' # CommandT::Matcher +require 'command-t/scanner/buffer_scanner' +require 'command-t/finder' + +module CommandT + class BufferFinder < Finder + def initialize + @scanner = BufferScanner.new + @matcher = Matcher.new @scanner, :always_show_dot_files => true + end + end # class BufferFinder +end # CommandT diff --git a/vim/bundle/Command-T/ruby/command-t/finder/file_finder.rb b/vim/bundle/Command-T/ruby/command-t/finder/file_finder.rb new file mode 100644 index 0000000..03d637b --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/finder/file_finder.rb @@ -0,0 +1,39 @@ +# Copyright 2010-2012 Wincent Colaiuta. 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. + +require 'command-t/ext' # CommandT::Matcher +require 'command-t/finder' +require 'command-t/scanner/file_scanner' + +module CommandT + class FileFinder < Finder + def initialize path = Dir.pwd, options = {} + @scanner = FileScanner.new path, options + @matcher = Matcher.new @scanner, options + end + + def flush + @scanner.flush + end + end # class FileFinder +end # CommandT diff --git a/vim/bundle/Command-T/ruby/command-t/finder/jump_finder.rb b/vim/bundle/Command-T/ruby/command-t/finder/jump_finder.rb new file mode 100644 index 0000000..19f6c09 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/finder/jump_finder.rb @@ -0,0 +1,35 @@ +# Copyright 2011 Wincent Colaiuta. 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. + +require 'command-t/ext' # CommandT::Matcher +require 'command-t/scanner/jump_scanner' +require 'command-t/finder' + +module CommandT + class JumpFinder < Finder + def initialize + @scanner = JumpScanner.new + @matcher = Matcher.new @scanner, :always_show_dot_files => true + end + end # class JumpFinder +end # module CommandT diff --git a/vim/bundle/Command-T/ruby/command-t/finder/tag_finder.rb b/vim/bundle/Command-T/ruby/command-t/finder/tag_finder.rb new file mode 100644 index 0000000..66777ee --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/finder/tag_finder.rb @@ -0,0 +1,44 @@ +# Copyright 2011-2012 Wincent Colaiuta. 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. + +require 'command-t/ext' # CommandT::Matcher +require 'command-t/scanner/tag_scanner' +require 'command-t/finder' + +module CommandT + class TagFinder < Finder + def initialize options = {} + @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 + end # class TagFinder +end # module CommandT diff --git a/vim/bundle/Command-T/ruby/command-t/match.c b/vim/bundle/Command-T/ruby/command-t/match.c new file mode 100644 index 0000000..e32fb0b --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/match.c @@ -0,0 +1,189 @@ +// Copyright 2010 Wincent Colaiuta. 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. + +#include "match.h" +#include "ext.h" +#include "ruby_compat.h" + +// use a struct to make passing params during recursion easier +typedef struct +{ + char *str_p; // pointer to string to be searched + long str_len; // length of same + char *abbrev_p; // pointer to search string (abbreviation) + long abbrev_len; // length of same + double max_score_per_char; + int dot_file; // boolean: true if str is a dot-file + int always_show_dot_files; // boolean + int never_show_dot_files; // boolean +} matchinfo_t; + +double recursive_match(matchinfo_t *m, // sharable meta-data + long str_idx, // where in the path string to start + long abbrev_idx, // where in the search string to start + long last_idx, // location of last matched character + double score) // cumulative score so far +{ + double seen_score = 0; // remember best score seen via recursion + int dot_file_match = 0; // true if abbrev matches a dot-file + int dot_search = 0; // true if searching for a dot + + for (long i = abbrev_idx; i < m->abbrev_len; i++) + { + char c = m->abbrev_p[i]; + if (c == '.') + dot_search = 1; + int found = 0; + for (long j = str_idx; j < m->str_len; j++, str_idx++) + { + char d = m->str_p[j]; + if (d == '.') + { + if (j == 0 || m->str_p[j - 1] == '/') + { + m->dot_file = 1; // this is a dot-file + if (dot_search) // and we are searching for a dot + dot_file_match = 1; // so this must be a match + } + } + else if (d >= 'A' && d <= 'Z') + d += 'a' - 'A'; // add 32 to downcase + if (c == d) + { + found = 1; + dot_search = 0; + + // calculate score + double score_for_char = m->max_score_per_char; + long distance = j - last_idx; + if (distance > 1) + { + double factor = 1.0; + char last = m->str_p[j - 1]; + char curr = m->str_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->str_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 = str_idx++; + break; + } + } + if (!found) + return 0.0; + } + if (m->dot_file) + { + if (m->never_show_dot_files || + (!dot_file_match && !m->always_show_dot_files)) + return 0.0; + } + return (score > seen_score) ? score : seen_score; +} + +// Match.new abbrev, string, options = {} +VALUE CommandTMatch_initialize(int argc, VALUE *argv, VALUE self) +{ + // process arguments: 2 mandatory, 1 optional + VALUE str, abbrev, options; + if (rb_scan_args(argc, argv, "21", &str, &abbrev, &options) == 2) + options = Qnil; + str = StringValue(str); + abbrev = StringValue(abbrev); // already downcased by caller + + // check optional options hash for overrides + VALUE always_show_dot_files = CommandT_option_from_hash("always_show_dot_files", options); + VALUE never_show_dot_files = CommandT_option_from_hash("never_show_dot_files", options); + + matchinfo_t m; + m.str_p = RSTRING_PTR(str); + m.str_len = RSTRING_LEN(str); + m.abbrev_p = RSTRING_PTR(abbrev); + m.abbrev_len = RSTRING_LEN(abbrev); + m.max_score_per_char = (1.0 / m.str_len + 1.0 / m.abbrev_len) / 2; + m.dot_file = 0; + m.always_show_dot_files = always_show_dot_files == Qtrue; + m.never_show_dot_files = never_show_dot_files == Qtrue; + + // calculate score + double score = 1.0; + if (m.abbrev_len == 0) // special case for zero-length search string + { + // filter out dot files + if (!m.always_show_dot_files) + { + for (long i = 0; i < m.str_len; i++) + { + char c = m.str_p[i]; + if (c == '.' && (i == 0 || m.str_p[i - 1] == '/')) + { + score = 0.0; + break; + } + } + } + } + else // normal case + score = recursive_match(&m, 0, 0, 0, 0.0); + + // clean-up and final book-keeping + rb_iv_set(self, "@score", rb_float_new(score)); + rb_iv_set(self, "@str", str); + return Qnil; +} + +VALUE CommandTMatch_matches(VALUE self) +{ + double score = NUM2DBL(rb_iv_get(self, "@score")); + return score > 0 ? Qtrue : Qfalse; +} + +VALUE CommandTMatch_to_s(VALUE self) +{ + return rb_iv_get(self, "@str"); +} diff --git a/vim/bundle/Command-T/ruby/command-t/match.h b/vim/bundle/Command-T/ruby/command-t/match.h new file mode 100644 index 0000000..c3ce929 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/match.h @@ -0,0 +1,29 @@ +// Copyright 2010 Wincent Colaiuta. 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. + +#include + +extern VALUE CommandTMatch_initialize(int argc, VALUE *argv, VALUE self); +extern VALUE CommandTMatch_matches(VALUE self); +extern VALUE CommandTMatch_score(VALUE self); +extern VALUE CommandTMatch_to_s(VALUE self); diff --git a/vim/bundle/Command-T/ruby/command-t/match_window.rb b/vim/bundle/Command-T/ruby/command-t/match_window.rb new file mode 100644 index 0000000..bda7fb1 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/match_window.rb @@ -0,0 +1,445 @@ +# Copyright 2010-2012 Wincent Colaiuta. 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. + +require 'ostruct' +require 'command-t/settings' + +module CommandT + class MatchWindow + SELECTION_MARKER = '> ' + MARKER_LENGTH = SELECTION_MARKER.length + UNSELECTED_MARKER = ' ' * MARKER_LENGTH + MH_START = '' + MH_END = '' + @@buffer = nil + + def initialize options = {} + @prompt = options[:prompt] + @reverse_list = options[:match_window_reverse] + @min_height = options[:min_height] + + # save existing window dimensions so we can restore them later + @windows = [] + (0..(::VIM::Window.count - 1)).each do |i| + @windows << OpenStruct.new(:index => i, + :height => ::VIM::Window[i].height, + :width => ::VIM::Window[i].width) + end + + # global settings (must manually save and restore) + @settings = Settings.new + ::VIM::set_option 'timeout' # ensure mappings timeout + ::VIM::set_option 'timeoutlen=0' # respond immediately to mappings + ::VIM::set_option 'nohlsearch' # don't highlight search strings + ::VIM::set_option 'noinsertmode' # don't make Insert mode the default + ::VIM::set_option 'noshowcmd' # don't show command info on last line + ::VIM::set_option 'report=9999' # don't show "X lines changed" reports + ::VIM::set_option 'sidescroll=0' # don't sidescroll in jumps + ::VIM::set_option 'sidescrolloff=0' # don't sidescroll automatically + ::VIM::set_option 'noequalalways' # don't auto-balance window sizes + + # 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 + split_command = "silent! #{split_location} 1split GoToFile" + [ + split_command, + 'setlocal bufhidden=unload', # unload buf when no longer displayed + 'setlocal buftype=nofile', # buffer is not related to any file + 'setlocal nomodifiable', # prevent manual edits + 'setlocal noswapfile', # don't create a swapfile + 'setlocal nowrap', # don't soft-wrap + 'setlocal nonumber', # don't show line numbers + 'setlocal nolist', # don't use List mode (visible tabs etc) + 'setlocal foldcolumn=0', # don't show a fold column at side + 'setlocal foldlevel=99', # don't fold anything + 'setlocal nocursorline', # don't highlight line cursor is on + 'setlocal nospell', # spell-checking off + 'setlocal nobuflisted', # don't show up in the buffer list + 'setlocal textwidth=0' # don't hard-wrap (break long lines) + ].each { |command| ::VIM::command command } + + # don't show the color column + ::VIM::command 'setlocal colorcolumn=0' if VIM::exists?('+colorcolumn') + + # don't show relative line numbers + ::VIM::command 'setlocal norelativenumber' 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 --$"' + ::VIM::command 'setlocal synmaxcol=9999' + + if VIM::has_conceal? + ::VIM::command 'setlocal conceallevel=2' + ::VIM::command 'setlocal 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 Visual' + ::VIM::command 'highlight link CommandTNoEntries Error' + ::VIM::evaluate 'clearmatches()' + + # 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. , etc) + ::VIM::command 'autocmd! * ' + ::VIM::command 'autocmd BufLeave silent! ruby $command_t.leave' + ::VIM::command 'autocmd BufUnload silent! ruby $command_t.unload' + + @has_focus = false + @selection = nil + @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 + if @selection < @matches.length - 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 + else + # (possibly) loop or scroll + end + end + + def select_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 + else + # (possibly) loop or scroll + end + end + + def matches= matches + matches = matches.reverse if @reverse_list + if matches != @matches + @matches = matches + @selection = @reverse_list ? @matches.length - 1 : 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 Visual' + 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? or @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.each_with_index do |match, idx| + if match[0, @find_string.length].casecmp(@find_string) == 0 + old_selection = @selection + @selection = 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 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 = [@selection + 1, 0] + end + + def print_error msg + return unless VIM::Window.select(@window) + unlock + clear + @window.height = @min_height > 0 ? @min_height : 1 + @@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.chars.to_a + match.chars.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[idx + 1] = match_text_for_idx idx + lock + 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 + actual_lines = 1 + @window_width = @window.width # update cached value + max_lines = VIM::Screen.lines - 5 + max_lines = 1 if max_lines < 0 + actual_lines = match_count < @min_height ? @min_height : match_count + actual_lines = max_lines if actual_lines > max_lines + @window.height = actual_lines + (1..actual_lines).each do |line| + idx = line - 1 + if @@buffer.count >= line + @@buffer[line] = match_text_for_idx idx + else + @@buffer.append line - 1, match_text_for_idx(idx) + 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 + ::VIM::command 'setlocal nomodifiable' + end + + def unlock + ::VIM::command 'setlocal modifiable' + end + end +end diff --git a/vim/bundle/Command-T/ruby/command-t/matcher.c b/vim/bundle/Command-T/ruby/command-t/matcher.c new file mode 100644 index 0000000..7cd8a3e --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/matcher.c @@ -0,0 +1,164 @@ +// Copyright 2010 Wincent Colaiuta. 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. + +#include /* for qsort() */ +#include /* for strcmp() */ +#include "matcher.h" +#include "ext.h" +#include "ruby_compat.h" + +// comparison function for use with qsort +int comp_alpha(const void *a, const void *b) +{ + VALUE a_val = *(VALUE *)a; + VALUE b_val = *(VALUE *)b; + ID to_s = rb_intern("to_s"); + + VALUE a_str = rb_funcall(a_val, to_s, 0); + VALUE b_str = rb_funcall(b_val, to_s, 0); + 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 comp_score(const void *a, const void *b) +{ + VALUE a_val = *(VALUE *)a; + VALUE b_val = *(VALUE *)b; + ID score = rb_intern("score"); + double a_score = RFLOAT_VALUE(rb_funcall(a_val, score, 0)); + double b_score = RFLOAT_VALUE(rb_funcall(b_val, score, 0)); + if (a_score > b_score) + return -1; // a scores higher, a should appear sooner + else if (a_score < b_score) + return 1; // b scores higher, a should appear later + else + return comp_alpha(a, b); +} + +VALUE CommandTMatcher_initialize(int argc, VALUE *argv, VALUE self) +{ + // process arguments: 1 mandatory, 1 optional + VALUE scanner, options; + 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 + VALUE always_show_dot_files = CommandT_option_from_hash("always_show_dot_files", options); + if (always_show_dot_files != Qtrue) + always_show_dot_files = Qfalse; + VALUE never_show_dot_files = CommandT_option_from_hash("never_show_dot_files", options); + if (never_show_dot_files != Qtrue) + never_show_dot_files = Qfalse; + 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; +} + +VALUE CommandTMatcher_sorted_matches_for(VALUE self, VALUE abbrev, VALUE options) +{ + // process optional options hash + VALUE limit_option = CommandT_option_from_hash("limit", options); + + // get unsorted matches + VALUE matches = CommandTMatcher_matches_for(self, abbrev); + + abbrev = StringValue(abbrev); + if (RSTRING_LEN(abbrev) == 0 || + (RSTRING_LEN(abbrev) == 1 && RSTRING_PTR(abbrev)[0] == '.')) + // alphabetic order if search string is only "" or "." + qsort(RARRAY_PTR(matches), RARRAY_LEN(matches), sizeof(VALUE), comp_alpha); + else + // for all other non-empty search strings, sort by score + qsort(RARRAY_PTR(matches), RARRAY_LEN(matches), sizeof(VALUE), comp_score); + + // apply optional limit option + long limit = NIL_P(limit_option) ? 0 : NUM2LONG(limit_option); + if (limit == 0 || RARRAY_LEN(matches) < limit) + limit = RARRAY_LEN(matches); + + // will return an array of strings, not an array of Match objects + for (long i = 0; i < limit; i++) + { + VALUE str = rb_funcall(RARRAY_PTR(matches)[i], rb_intern("to_s"), 0); + RARRAY_PTR(matches)[i] = str; + } + + // trim off any items beyond the limit + if (limit < RARRAY_LEN(matches)) + (void)rb_funcall(matches, rb_intern("slice!"), 2, LONG2NUM(limit), + LONG2NUM(RARRAY_LEN(matches) - limit)); + return matches; +} + +VALUE CommandTMatcher_matches_for(VALUE self, VALUE abbrev) +{ + if (NIL_P(abbrev)) + rb_raise(rb_eArgError, "nil abbrev"); + VALUE matches = rb_ary_new(); + VALUE scanner = rb_iv_get(self, "@scanner"); + VALUE always_show_dot_files = rb_iv_get(self, "@always_show_dot_files"); + VALUE never_show_dot_files = rb_iv_get(self, "@never_show_dot_files"); + VALUE options = Qnil; + if (always_show_dot_files == Qtrue) + { + options = rb_hash_new(); + rb_hash_aset(options, ID2SYM(rb_intern("always_show_dot_files")), always_show_dot_files); + } + else if (never_show_dot_files == Qtrue) + { + options = rb_hash_new(); + rb_hash_aset(options, ID2SYM(rb_intern("never_show_dot_files")), never_show_dot_files); + } + abbrev = rb_funcall(abbrev, rb_intern("downcase"), 0); + VALUE paths = rb_funcall(scanner, rb_intern("paths"), 0); + for (long i = 0, max = RARRAY_LEN(paths); i < max; i++) + { + VALUE path = RARRAY_PTR(paths)[i]; + VALUE match = rb_funcall(cCommandTMatch, rb_intern("new"), 3, path, abbrev, options); + if (rb_funcall(match, rb_intern("matches?"), 0) == Qtrue) + rb_funcall(matches, rb_intern("push"), 1, match); + } + return matches; +} diff --git a/vim/bundle/Command-T/ruby/command-t/matcher.h b/vim/bundle/Command-T/ruby/command-t/matcher.h new file mode 100644 index 0000000..6207e37 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/matcher.h @@ -0,0 +1,30 @@ +// Copyright 2010 Wincent Colaiuta. 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. + +#include + +extern VALUE CommandTMatcher_initialize(int argc, VALUE *argv, VALUE self); +extern VALUE CommandTMatcher_sorted_matches_for(VALUE self, VALUE abbrev, VALUE options); + +// most likely the function will be subsumed by the sorted_matcher_for function +extern VALUE CommandTMatcher_matches_for(VALUE self, VALUE abbrev); diff --git a/vim/bundle/Command-T/ruby/command-t/prompt.rb b/vim/bundle/Command-T/ruby/command-t/prompt.rb new file mode 100644 index 0000000..743e873 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/prompt.rb @@ -0,0 +1,165 @@ +# Copyright 2010 Wincent Colaiuta. 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. + +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 + + # 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 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 + + def focus + unless @has_focus + @has_focus = true + redraw + end + end + + def unfocus + if @has_focus + @has_focus = false + redraw + end + end + + private + + # 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) and (text = args.shift) do + 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 diff --git a/vim/bundle/Command-T/ruby/command-t/ruby_compat.h b/vim/bundle/Command-T/ruby/command-t/ruby_compat.h new file mode 100644 index 0000000..e7960a2 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/ruby_compat.h @@ -0,0 +1,49 @@ +// Copyright 2010 Wincent Colaiuta. 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. + +#include + +// 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 diff --git a/vim/bundle/Command-T/ruby/command-t/scanner.rb b/vim/bundle/Command-T/ruby/command-t/scanner.rb new file mode 100644 index 0000000..5e5e3c9 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/scanner.rb @@ -0,0 +1,28 @@ +# Copyright 2010-2011 Wincent Colaiuta. 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. + +require 'command-t/vim' + +module CommandT + class Scanner; end +end # module CommandT diff --git a/vim/bundle/Command-T/ruby/command-t/scanner/buffer_scanner.rb b/vim/bundle/Command-T/ruby/command-t/scanner/buffer_scanner.rb new file mode 100644 index 0000000..aa85497 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/scanner/buffer_scanner.rb @@ -0,0 +1,42 @@ +# Copyright 2010-2011 Wincent Colaiuta. 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. + +require 'command-t/vim' +require 'command-t/vim/path_utilities' +require 'command-t/scanner' + +module CommandT + # Returns a list of all open buffers. + class BufferScanner < Scanner + include VIM::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 # module CommandT diff --git a/vim/bundle/Command-T/ruby/command-t/scanner/file_scanner.rb b/vim/bundle/Command-T/ruby/command-t/scanner/file_scanner.rb new file mode 100644 index 0000000..e0dc3bc --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/scanner/file_scanner.rb @@ -0,0 +1,101 @@ +# Copyright 2010-2011 Wincent Colaiuta. 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. + +require 'command-t/vim' +require 'command-t/scanner' + +module CommandT + # Reads the current directory recursively for the paths to all regular files. + class FileScanner < Scanner + class FileLimitExceeded < ::RuntimeError; end + 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] || 10_000 + @max_caches = options[:max_caches] || 1 + @scan_dot_directories = options[:scan_dot_directories] || false + end + + def paths + return @paths[@path] if @paths.has_key?(@path) + begin + ensure_cache_under_limit + @paths[@path] = [] + @depth = 0 + @files = 0 + @prefix_len = @path.chomp('/').length + add_paths_for_directory @path, @paths[@path] + rescue FileLimitExceeded + end + @paths[@path] + end + + def flush + @paths = {} + end + + private + + 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 + # first strip common prefix (@path) from path to match VIM's behavior + path = path[(@prefix_len + 1)..-1] + path = VIM::escape_for_single_quotes path + ::VIM::evaluate("empty(expand(fnameescape('#{path}')))").to_i == 1 + 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..-1] + elsif File.directory?(path) + next if @depth >= @max_depth + next if (entry.match(/\A\./) && !@scan_dot_directories) + @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 + end + end # class FileScanner +end # module CommandT diff --git a/vim/bundle/Command-T/ruby/command-t/scanner/jump_scanner.rb b/vim/bundle/Command-T/ruby/command-t/scanner/jump_scanner.rb new file mode 100644 index 0000000..3da0f28 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/scanner/jump_scanner.rb @@ -0,0 +1,54 @@ +# Copyright 2011 Wincent Colaiuta. 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. + +require 'command-t/vim' +require 'command-t/vim/path_utilities' +require 'command-t/scanner' + +module CommandT + # Returns a list of files in the jumplist. + class JumpScanner < Scanner + include VIM::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 # module CommandT diff --git a/vim/bundle/Command-T/ruby/command-t/scanner/tag_scanner.rb b/vim/bundle/Command-T/ruby/command-t/scanner/tag_scanner.rb new file mode 100644 index 0000000..a9b8ddc --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/scanner/tag_scanner.rb @@ -0,0 +1,49 @@ +# Copyright 2011-2012 Wincent Colaiuta. 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. + +require 'command-t/vim' +require 'command-t/scanner' + +module CommandT + class TagScanner < Scanner + attr_reader :include_filenames + + def initialize options = {} + @include_filenames = options[:include_filenames] || false + end + + def paths + taglist.map do |tag| + path = tag['name'] + path << ":#{tag['filename']}" if @include_filenames + path + end.uniq.sort + end + + private + + def taglist + ::VIM::evaluate 'taglist(".")' + end + end # class TagScanner +end # module CommandT diff --git a/vim/bundle/Command-T/ruby/command-t/settings.rb b/vim/bundle/Command-T/ruby/command-t/settings.rb new file mode 100644 index 0000000..c15016a --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/settings.rb @@ -0,0 +1,77 @@ +# Copyright 2010 Wincent Colaiuta. 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. + +module CommandT + # Convenience class for saving and restoring global settings. + class Settings + def initialize + save + end + + def save + @timeoutlen = get_number 'timeoutlen' + @report = get_number 'report' + @sidescroll = get_number 'sidescroll' + @sidescrolloff = get_number 'sidescrolloff' + @timeout = get_bool 'timeout' + @equalalways = get_bool 'equalalways' + @hlsearch = get_bool 'hlsearch' + @insertmode = get_bool 'insertmode' + @showcmd = get_bool 'showcmd' + end + + def restore + set_number 'timeoutlen', @timeoutlen + set_number 'report', @report + set_number 'sidescroll', @sidescroll + set_number 'sidescrolloff', @sidescrolloff + set_bool 'timeout', @timeout + set_bool 'equalalways', @equalalways + set_bool 'hlsearch', @hlsearch + set_bool 'insertmode', @insertmode + set_bool 'showcmd', @showcmd + end + + private + + def get_number setting + ::VIM::evaluate("&#{setting}").to_i + end + + def get_bool setting + ::VIM::evaluate("&#{setting}").to_i == 1 + end + + def set_number setting, value + ::VIM::set_option "#{setting}=#{value}" + end + + def set_bool setting, value + if value + ::VIM::set_option setting + else + ::VIM::set_option "no#{setting}" + end + end + end # class Settings +end # module CommandT diff --git a/vim/bundle/Command-T/ruby/command-t/stub.rb b/vim/bundle/Command-T/ruby/command-t/stub.rb new file mode 100644 index 0000000..4628b61 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/stub.rb @@ -0,0 +1,42 @@ +# Copyright 2010-2011 Wincent Colaiuta. 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. + +module CommandT + class Stub + @@load_error = ['command-t.vim could not load the C extension', + 'Please see INSTALLATION and TROUBLE-SHOOTING in the help', + 'For more information type: :help command-t'] + + [:flush, :show_buffer_finder, :show_file_finder, :show_tag_finder].each do |method| + define_method(method.to_sym) { 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 diff --git a/vim/bundle/Command-T/ruby/command-t/vim.rb b/vim/bundle/Command-T/ruby/command-t/vim.rb new file mode 100644 index 0000000..fc75738 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/vim.rb @@ -0,0 +1,59 @@ +# Copyright 2010-2012 Wincent Colaiuta. 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. + +require 'command-t/vim/screen' +require 'command-t/vim/window' + +module CommandT + module VIM + def self.has_syntax? + ::VIM::evaluate('has("syntax")').to_i != 0 + end + + def self.exists? str + ::VIM::evaluate(%{exists("#{str}")}).to_i != 0 + end + + def self.has_conceal? + ::VIM::evaluate('has("conceal")').to_i != 0 + end + + def self.pwd + ::VIM::evaluate 'getcwd()' + end + + # Execute cmd, capturing the output into a variable and returning it. + def self.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 self.escape_for_single_quotes str + str.gsub "'", "''" + end + end # module VIM +end # module CommandT diff --git a/vim/bundle/Command-T/ruby/command-t/vim/path_utilities.rb b/vim/bundle/Command-T/ruby/command-t/vim/path_utilities.rb new file mode 100644 index 0000000..8564300 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/vim/path_utilities.rb @@ -0,0 +1,40 @@ +# Copyright 2010-2011 Wincent Colaiuta. 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. + +require 'command-t/vim' + +module CommandT + module VIM + 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 VIM +end # module CommandT diff --git a/vim/bundle/Command-T/ruby/command-t/vim/screen.rb b/vim/bundle/Command-T/ruby/command-t/vim/screen.rb new file mode 100644 index 0000000..fb7ba33 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/vim/screen.rb @@ -0,0 +1,32 @@ +# Copyright 2010 Wincent Colaiuta. 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. + +module CommandT + module VIM + module Screen + def self.lines + ::VIM::evaluate('&lines').to_i + end + end # module Screen + end # module VIM +end # module CommandT diff --git a/vim/bundle/Command-T/ruby/command-t/vim/window.rb b/vim/bundle/Command-T/ruby/command-t/vim/window.rb new file mode 100644 index 0000000..1e53d56 --- /dev/null +++ b/vim/bundle/Command-T/ruby/command-t/vim/window.rb @@ -0,0 +1,38 @@ +# Copyright 2010 Wincent Colaiuta. 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. + +module CommandT + module VIM + class Window + def self.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 # class Window + end # module VIM +end # module CommandT diff --git a/vim/bundle/Command-T/spec/command-t/controller_spec.rb b/vim/bundle/Command-T/spec/command-t/controller_spec.rb new file mode 100644 index 0000000..573f784 --- /dev/null +++ b/vim/bundle/Command-T/spec/command-t/controller_spec.rb @@ -0,0 +1,102 @@ +# Copyright 2010-2011 Wincent Colaiuta. 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. + +require 'spec_helper' +require 'command-t/controller' + +module VIM; end + +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 + + it 'opens relative paths inside the working directory' do + stub(::VIM).evaluate('a:arg').returns('') + 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::FileFinder.new + stub(finder).path = anything + stub(finder).sorted_matches_for(anything, anything).returns(sorted_matches) + stub(CommandT::FileFinder).new.returns(finder) + end + + def stub_match_window(selection) + match_window = Object.new + stub(match_window).matches = anything + stub(match_window).close + 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).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 diff --git a/vim/bundle/Command-T/spec/command-t/finder/buffer_finder_spec.rb b/vim/bundle/Command-T/spec/command-t/finder/buffer_finder_spec.rb new file mode 100644 index 0000000..b062e91 --- /dev/null +++ b/vim/bundle/Command-T/spec/command-t/finder/buffer_finder_spec.rb @@ -0,0 +1,78 @@ +# Copyright 2010-2011 Wincent Colaiuta. 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. + +require 'spec_helper' +require 'command-t/finder/buffer_finder' + +module VIM; end + +describe CommandT::BufferFinder do + before do + @paths = %w(.git/config .vim/notes .vimrc baz foo/beta) + any_instance_of(CommandT::BufferScanner, :paths => @paths) + @finder = CommandT::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 diff --git a/vim/bundle/Command-T/spec/command-t/finder/file_finder_spec.rb b/vim/bundle/Command-T/spec/command-t/finder/file_finder_spec.rb new file mode 100644 index 0000000..3150cd5 --- /dev/null +++ b/vim/bundle/Command-T/spec/command-t/finder/file_finder_spec.rb @@ -0,0 +1,80 @@ +# Copyright 2010-2011 Wincent Colaiuta. 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. + +require 'spec_helper' +require 'command-t/finder/file_finder' + +module VIM; end + +describe CommandT::FileFinder do + before :all do + @finder = CommandT::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 + # scanner will call VIM's expand() function for exclusion filtering + 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 diff --git a/vim/bundle/Command-T/spec/command-t/match_spec.rb b/vim/bundle/Command-T/spec/command-t/match_spec.rb new file mode 100644 index 0000000..5ee5ba1 --- /dev/null +++ b/vim/bundle/Command-T/spec/command-t/match_spec.rb @@ -0,0 +1,236 @@ +# Copyright 2010 Wincent Colaiuta. 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. + +require 'spec_helper' +require 'command-t/ext' + +describe CommandT::Match do + def match_for path, pattern + CommandT::Match.new path, pattern + end + + it 'requires pattern to be lowercase' do + # this is an optimization: we ask our caller (the Matcher class) to + # downcase once before calling us, rather than downcase repeatedly + # during looping, recursion, and initialization of thousands of Match + # instances + match_for('foo', 'Foo').matches?.should == false + end + + describe '#matches?' do + it 'returns false for non-matches' do + match_for('foo', 'bar').matches?.should == false + end + + it 'returns true for matches' do + match_for('foo', 'foo').matches?.should == true + end + + it 'returns true for empty search strings' do + match_for('foo', '').matches?.should == true + end + + it 'returns false for overlength matches' do + match_for('foo', 'foo...').matches?.should == false + end + end + + describe 'score method' do + it 'assigns a score of 1.0 for empty search string' do + match_for('foo', '').score.should == 1.0 + end + + it 'assigns a score of zero for a non-match' do + match_for('foo', 'bar').score.should == 0.0 + end + + it 'assigns a score of zero for an overlength match' do + match_for('foo', 'foo...').score.should == 0.0 + end + + it 'assigns perfect matches a score of one' do + match_for('foo', 'foo').score.should == 1.0 + end + + it 'assigns perfect but incomplete matches a score of less than one' do + match_for('foo', 'f').score.should < 1.0 + end + + it 'prioritizes matches with more matching characters' do + few_matches = match_for('foobar', 'fb') + many_matches = match_for('foobar', 'fbar') + many_matches.score.should > few_matches.score + end + + it 'prioritizes shorter paths over longer ones' do + short_path = match_for('article.rb', 'art') + long_path = match_for('articles_controller_spec.rb', 'art') + short_path.score.should > long_path.score + end + + it 'prioritizes matches after "/"' do + normal_match = match_for('fooobar', 'b') + special_match = match_for('foo/bar', 'b') + special_match.score.should > normal_match.score + + # note that / beats _ + normal_match = match_for('foo_bar', 'b') + special_match = match_for('foo/bar', 'b') + special_match.score.should > normal_match.score + + # / also beats - + normal_match = match_for('foo-bar', 'b') + special_match = match_for('foo/bar', 'b') + special_match.score.should > normal_match.score + + # and numbers + normal_match = match_for('foo9bar', 'b') + special_match = match_for('foo/bar', 'b') + special_match.score.should > normal_match.score + + # and periods + normal_match = match_for('foo.bar', 'b') + special_match = match_for('foo/bar', 'b') + special_match.score.should > normal_match.score + + # and spaces + normal_match = match_for('foo bar', 'b') + special_match = match_for('foo/bar', 'b') + special_match.score.should > normal_match.score + end + + it 'prioritizes matches after "-"' do + normal_match = match_for('fooobar', 'b') + special_match = match_for('foo-bar', 'b') + special_match.score.should > normal_match.score + + # - also beats . + normal_match = match_for('foo.bar', 'b') + special_match = match_for('foo-bar', 'b') + special_match.score.should > normal_match.score + end + + it 'prioritizes matches after "_"' do + normal_match = match_for('fooobar', 'b') + special_match = match_for('foo_bar', 'b') + special_match.score.should > normal_match.score + + # _ also beats . + normal_match = match_for('foo.bar', 'b') + special_match = match_for('foo_bar', 'b') + special_match.score.should > normal_match.score + end + + it 'prioritizes matches after " "' do + normal_match = match_for('fooobar', 'b') + special_match = match_for('foo bar', 'b') + special_match.score.should > normal_match.score + + # " " also beats . + normal_match = match_for('foo.bar', 'b') + special_match = match_for('foo bar', 'b') + special_match.score.should > normal_match.score + end + + it 'prioritizes matches after numbers' do + normal_match = match_for('fooobar', 'b') + special_match = match_for('foo9bar', 'b') + special_match.score.should > normal_match.score + + # numbers also beat . + normal_match = match_for('foo.bar', 'b') + special_match = match_for('foo9bar', 'b') + special_match.score.should > normal_match.score + end + + it 'prioritizes matches after periods' do + normal_match = match_for('fooobar', 'b') + special_match = match_for('foo.bar', 'b') + special_match.score.should > normal_match.score + end + + it 'prioritizes matching capitals following lowercase' do + normal_match = match_for('foobar', 'b') + special_match = match_for('fooBar', 'b') + special_match.score.should > normal_match.score + end + + it 'prioritizes matches earlier in the string' do + early_match = match_for('**b*****', 'b') + late_match = match_for('******b*', 'b') + early_match.score.should > late_match.score + end + + it 'prioritizes matches closer to previous matches' do + early_match = match_for('**bc****', 'bc') + late_match = match_for('**b***c*', 'bc') + early_match.score.should > late_match.score + end + + it 'scores alternative matches of same path differently' do + # given path: app/controllers/articles_controller.rb + left_to_right_match = match_for('a**/****r******/**t*c***_*on*******.**', 'artcon') + best_match = match_for('***/***********/art*****_con*******.**', 'artcon') + best_match.score.should > left_to_right_match.score + end + + it 'returns the best possible score among alternatives' do + # given path: app/controllers/articles_controller.rb + best_match = match_for('***/***********/art*****_con*******.**', 'artcon') + chosen_match = match_for('app/controllers/articles_controller.rb', 'artcon') + chosen_match.score.should == best_match.score + end + + it 'provides intuitive results for "artcon" and "articles_controller"' do + low = match_for('app/controllers/heartbeat_controller.rb', 'artcon') + high = match_for('app/controllers/articles_controller.rb', 'artcon') + high.score.should > low.score + end + + it 'provides intuitive results for "aca" and "a/c/articles_controller"' do + low = match_for 'app/controllers/heartbeat_controller.rb', 'aca' + high = match_for 'app/controllers/articles_controller.rb', 'aca' + best_match = match_for 'a**/c**********/a******************.**', 'aca' + high.score.should > low.score + high.score.should == best_match.score + end + + it 'provides intuitive results for "d" and "doc/command-t.txt"' do + low = match_for 'TODO', 'd' + high = match_for 'doc/command-t.txt', 'd' + high.score.should > low.score + end + + it 'provides intuitive results for "do" and "doc/command-t.txt"' do + low = match_for 'TODO', 'do' + high = match_for 'doc/command-t.txt', 'do' + high.score.should > low.score + end + end + + describe 'to_s method' do + it 'returns the entire matched string' do + match_for('abc', 'abc').to_s.should == 'abc' + end + end +end diff --git a/vim/bundle/Command-T/spec/command-t/matcher_spec.rb b/vim/bundle/Command-T/spec/command-t/matcher_spec.rb new file mode 100644 index 0000000..324e4a9 --- /dev/null +++ b/vim/bundle/Command-T/spec/command-t/matcher_spec.rb @@ -0,0 +1,78 @@ +# Copyright 2010 Wincent Colaiuta. 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. + +require 'spec_helper' +require 'command-t/scanner' +require 'command-t/ext' + +describe CommandT::Matcher do + describe 'initialization' do + it 'raises an ArgumentError if passed nil' do + expect do + CommandT::Matcher.new nil + end.to raise_error(ArgumentError) + end + end + + describe '#matches_for' do + before do + @scanner = Object.new + end + + it 'raises an ArgumentError if passed nil' do + @matcher = CommandT::Matcher.new @scanner + expect do + @matcher.matches_for(nil) + end.to raise_error(ArgumentError) + end + + it 'returns empty array when source array empty' do + stub(@scanner).paths { [] } + @no_paths = CommandT::Matcher.new @scanner + @no_paths.matches_for('foo').should == [] + @no_paths.matches_for('').should == [] + end + + it 'returns empty array when no matches' do + stub(@scanner).paths { ['foo/bar', 'foo/baz', 'bing'] } + @no_matches = CommandT::Matcher.new @scanner + @no_matches.matches_for('xyz').should == [] + end + + it 'returns matching paths' do + stub(@scanner).paths { ['foo/bar', 'foo/baz', 'bing'] } + @foo_paths = CommandT::Matcher.new @scanner + matches = @foo_paths.matches_for('z') + matches.map { |m| m.to_s }.should == ['foo/baz'] + matches = @foo_paths.matches_for('bg') + matches.map { |m| m.to_s }.should == ['bing'] + end + + it 'performs case-insensitive matching' do + stub(@scanner).paths { ['Foo'] } + @path = CommandT::Matcher.new @scanner + matches = @path.matches_for('f') + matches.map { |m| m.to_s }.should == ['Foo'] + end + end +end diff --git a/vim/bundle/Command-T/spec/command-t/scanner/buffer_scanner_spec.rb b/vim/bundle/Command-T/spec/command-t/scanner/buffer_scanner_spec.rb new file mode 100644 index 0000000..fdfd203 --- /dev/null +++ b/vim/bundle/Command-T/spec/command-t/scanner/buffer_scanner_spec.rb @@ -0,0 +1,54 @@ +# Copyright 2010-2011 Wincent Colaiuta. 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. + +require 'spec_helper' +require 'ostruct' +require 'command-t/scanner/buffer_scanner' + +module VIM + class Buffer; end +end + +describe CommandT::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::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 diff --git a/vim/bundle/Command-T/spec/command-t/scanner/file_scanner_spec.rb b/vim/bundle/Command-T/spec/command-t/scanner/file_scanner_spec.rb new file mode 100644 index 0000000..0e4d405 --- /dev/null +++ b/vim/bundle/Command-T/spec/command-t/scanner/file_scanner_spec.rb @@ -0,0 +1,83 @@ +# Copyright 2010-2011 Wincent Colaiuta. 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. + +require 'spec_helper' +require 'command-t/scanner/file_scanner' + +module VIM; end + +describe CommandT::FileScanner 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::FileScanner.new @dir + + # scanner will call VIM's expand() function for exclusion filtering + stub(::VIM).evaluate(/expand\(.+\)/) { '0' } + end + + describe 'paths method' do + it 'returns a list of regular files' do + @scanner.paths.should =~ @all_fixtures + end + end + + describe 'flush method' do + it 'forces a rescan on next call to paths method' do + first = @scanner.paths + @scanner.flush + @scanner.paths.object_id.should_not == first.object_id + 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 + it "calls on VIM's expand() function for pattern filtering" do + @scanner = CommandT::FileScanner.new @dir + mock(::VIM).evaluate(/expand\(.+\)/).times(10) + @scanner.paths + end + end + + describe ':max_depth option' do + it 'does not descend below "max_depth" levels' do + @scanner = CommandT::FileScanner.new @dir, :max_depth => 1 + @scanner.paths.should =~ %w(bar/abc bar/xyz baz bing foo/beta) + end + end +end diff --git a/vim/bundle/Command-T/spec/spec_helper.rb b/vim/bundle/Command-T/spec/spec_helper.rb new file mode 100644 index 0000000..f0831c2 --- /dev/null +++ b/vim/bundle/Command-T/spec/spec_helper.rb @@ -0,0 +1,38 @@ +# Copyright 2010 Wincent Colaiuta. 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. + +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 + +RSpec.configure do |config| + config.mock_framework = :rr +end diff --git a/vim/bundle/Command-T/spec/vim_formatter.rb b/vim/bundle/Command-T/spec/vim_formatter.rb new file mode 100644 index 0000000..6ad902f --- /dev/null +++ b/vim/bundle/Command-T/spec/vim_formatter.rb @@ -0,0 +1,41 @@ +require 'spec/runner/formatter/base_text_formatter' +require 'pathname' + +# Format spec results for display in the Vim quickfix window +# Use this custom formatter like this: +# spec -r spec/vim_formatter.rb -f Spec::Runner::Formatter::VimFormatter spec +module Spec + module Runner + module Formatter + class VimFormatter < BaseTextFormatter + + # TODO: handle pending issues + # TODO: vim-side function for printing progress + def dump_failure counter, failure + path = failure.exception.backtrace.find do |frame| + frame =~ %r{\bspec/.*_spec\.rb:\d+\z} + end + message = failure.exception.message.gsub("\n", ' ') + @output.puts "#{relativize_path(path)}: #{message}" if path + end + + def dump_pending; end + + def dump_summary duration, example_count, failure_count, pending_count + end + + private + + def relativize_path path + @wd ||= Pathname.new Dir.getwd + begin + return Pathname.new(path).relative_path_from(@wd) + rescue ArgumentError + # raised unless both paths relative, or both absolute + return path + end + end + end # class VimFormatter + end # module Formatter + end # module Runner +end # module Spec diff --git a/vim/bundle/vim-ruby-debugger/.gitattributes b/vim/bundle/vim-ruby-debugger/.gitattributes deleted file mode 100644 index e703d62..0000000 --- a/vim/bundle/vim-ruby-debugger/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -additionals/autoload/ruby_debugger.vim -diff -vim/autoload/ruby_debugger.vim -diff diff --git a/vim/bundle/vim-ruby-debugger/.gitignore b/vim/bundle/vim-ruby-debugger/.gitignore deleted file mode 100644 index 413d15f..0000000 --- a/vim/bundle/vim-ruby-debugger/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*.swp -*.un~ -tmp -doc/tags diff --git a/vim/bundle/vim-ruby-debugger/README.md b/vim/bundle/vim-ruby-debugger/README.md deleted file mode 100644 index 183167f..0000000 --- a/vim/bundle/vim-ruby-debugger/README.md +++ /dev/null @@ -1,113 +0,0 @@ -# Description # - -This Vim plugin implements interactive Ruby debugger in Vim. - - -# Features # - -1. It can debug any Ruby application (Rails, by default), using **ruby-debug-ide** gem -2. The debugger looks like in the Netbeans - you can go through the code, watch variables, breakpoints in separate window, set and remove breakpoints. -3. It supports command-line rdebug commands. E.g., you can execute ':RdbCommand p User.all' in command line of VIM and it will display result like usual echo VIM command. - - -# Requirements # - -1. Vim >= 7.0, compiled with +signs and +clientserver. You can verify it by VIM command: - - :echo has("signs") && has("clientserver") && v:version > 700 - - It should show result '1'. - -2. ruby-debug-ide gem. -3. For linux: 'lsof' program. -4. For OS X: - - The vim that ships with OS X does not use ruby, nor does it support --servername, so MacVim must be used. - - Make sure that both MacVim, and mvim are installed. - - If they are not, you can use homebrew (http://mxcl.github.com/homebrew/): - - brew install macvim - - This will install MacVim, along with the mvim command line utility. - -# Installation # - -1. Clone the repo - - git clone git://github.com/astashov/vim-ruby-debugger.git - - or just download the archive from here: - - http://github.com/astashov/vim-ruby-debugger/tarball/master - - You will get the 'vim-ruby-debugger' dir with the plugin. - -2. Copy contents of the 'vim-ruby-debugger' dir to your ~/.vim/ (or to ~/.vim/bundle/vim-ruby-debugger if you use pathogen). - -3. Generate the local tags file - - :helptags ~/.vim/doc - - Now, you can use - - :help ruby-debugger - - to get help for the ruby-debugger plugin. - -4. If using MacVim: - - Modify your ~/.vimrc to add the following line: - - ```VimL - let g:ruby_debugger_progname = 'mvim' - ``` - -I've tested the plugin in Windows and Linux. All tests should be passed there. - - -# Using# - -1. Run Vim. If you use gvim, it will automatically start the server, but if you use vim, you need to set - servername explicitly, e.g., **vim --servername VIM** - -2. Go to the directory with some your Rails application. - - :cd ~/projects/rails - -3. Run Server with Debugger: - - :Rdebugger - - It will kill any listeners of ports 39767 and 39768 and run rdebug-ide and ~/.vim/bin/ruby_debugger.rb on these ports accordingly. - -3. Set breakpoint somewhere by **<Leader>b** (e.g., '\b'). You should see 'xx' symbol at current line. - -4. Open page with the breakpoint in the browser. Vim should automatically set current line to breakpoint. - -5. After this, you can use commands: - - b - set breakpoint at current line - v - open/close window with variables. You can expand/collapse variables by 'o' in normal mode or left-mouse double-click - n - step over - s - step into - c - continue - - -# Testing # - -If you want to run tests, replace in /autoload directory ruby_debugger.vim to **ruby_debugger.vim** from additionals/autoload directory. -And then, in command mode execute - - :call g:TU.run() - - -# Screenshot # - -![Screenshot](http://astashov.net/images/vim_ruby_debugger.png) - - -# Thanks # - -Special thanks to tpope (for rails.vim) and Marty Grenfell (for NERDTree), mostly, I learn Vim Scripting from their projects. diff --git a/vim/bundle/vim-ruby-debugger/autoload/ruby_debugger.vim b/vim/bundle/vim-ruby-debugger/autoload/ruby_debugger.vim deleted file mode 100644 index 35f16d0..0000000 --- a/vim/bundle/vim-ruby-debugger/autoload/ruby_debugger.vim +++ /dev/null @@ -1,2055 +0,0 @@ -" Init section - set default values, highlight colors - -let s:rdebug_port = 39767 -let s:debugger_port = 39768 -" hostname() returns something strange in Windows (E98BD9A419BB41D), so set hostname explicitly -let s:hostname = '127.0.0.1' "hostname() -" ~/.vim for Linux, vimfiles for Windows -let s:runtime_dir = expand(':h:h') -" File for communicating between intermediate Ruby script ruby_debugger.rb and -" this plugin -let s:tmp_file = s:runtime_dir . '/tmp/ruby_debugger' -let s:logger_file = s:runtime_dir . '/tmp/ruby_debugger_log' -let s:server_output_file = s:runtime_dir . '/tmp/ruby_debugger_output' -" Default id for sign of current line -let s:current_line_sign_id = 120 -let s:separator = "++vim-ruby-debugger separator++" -let s:sign_id = 0 - -" Create tmp directory if it doesn't exist -if !isdirectory(s:runtime_dir . '/tmp') - call mkdir(s:runtime_dir . '/tmp') -endif - -" Init breakpoint signs -hi def link Breakpoint Error -sign define breakpoint linehl=Breakpoint text=xx - -" Init current line signs -hi def link CurrentLine DiffAdd -sign define current_line linehl=CurrentLine text=>> - -" Loads this file. Required for autoloading the code for this plugin -fun! ruby_debugger#load_debugger() - if !s:check_prerequisites() - finish - endif -endf - -fun! ruby_debugger#statusline() - let is_running = g:RubyDebugger.is_running() - if is_running == 0 - return '' - endif - return '[ruby debugger running]' -endfunction - -" Check all requirements for the current plugin -fun! s:check_prerequisites() - let problems = [] - if v:version < 700 - call add(problems, "RubyDebugger: This plugin requires Vim >= 7.") - endif - if !has("clientserver") - call add(problems, "RubyDebugger: This plugin requires +clientserver option") - endif - if !executable("rdebug-ide") - call add(problems, "RubyDebugger: You don't have installed 'ruby-debug-ide' gem or executable 'rdebug-ide' can't be found in your PATH") - endif - if !(has("win32") || has("win64")) && !executable("lsof") - call add(problems, "RubyDebugger: You don't have 'lsof' installed or executable 'lsof' can't be found in your PATH") - endif - if g:ruby_debugger_builtin_sender && !has("ruby") - call add(problems, "RubyDebugger: You are trying to use built-in Ruby in Vim, but your Vim doesn't compiled with +ruby. Set g:ruby_debugger_builtin_sender = 0 in your .vimrc to resolve that issue.") - end - if empty(problems) - return 1 - else - for p in problems - echoerr p - endfor - return 0 - endif -endf - - -" End of init section - - -" *** Common (global) functions - -" Split string of tags to List. E.g., -" -" will be splitted to -" [ '', '' ] -function! s:get_tags(cmd) - let tags = [] - let cmd = a:cmd - " Remove wrap tags - let inner_tags_match = s:get_inner_tags(cmd) - if !empty(inner_tags_match) - " Then find every tag and remove it from source string - let pattern = '<.\{-}\/>' - let inner_tags = inner_tags_match[1] - let tagmatch = matchlist(inner_tags, pattern) - while empty(tagmatch) == 0 - call add(tags, tagmatch[0]) - " These symbols are interpretated as special, we need to escape them - let tagmatch[0] = escape(tagmatch[0], '[]~*\') - " Remove it from source string - let inner_tags = substitute(inner_tags, tagmatch[0], '', '') - " Find next tag - let tagmatch = matchlist(inner_tags, pattern) - endwhile - endif - return tags -endfunction - - -" Converts command with relative path to absolute path. If given command -" contains relative path, it will try to use 'which' on it first, and if -" 'which' returns nothing, it will add current dir path to given command -function! s:get_escaped_absolute_path(command) - " Remove leading and trailing quotes - let given_path = a:command - let given_path = substitute(given_path, '"', '\"', "g") - let given_path = substitute(given_path, "^'", '', "g") - let given_path = substitute(given_path, "'$", '', "g") - if given_path[0] == '/' - let absolute_path = given_path - else - let parts = split(given_path) - let relative_command = remove(parts, 0) - let arguments = join(parts) - let absolute_command = "" - " I don't know Windows analogue for 'which', if you know - feel free to add it here - if !(has("win32") || has("win64")) - let absolute_command = s:strip(system('which ' . relative_command)) - endif - if absolute_command[0] != '/' - let absolute_command = getcwd() . '/' . relative_command - endif - let absolute_path = "\"'" . absolute_command . "' " . arguments . '"' - endif - return absolute_path -endfunction - - -" Return a string without leading and trailing spaces and linebreaks. -function! s:strip(input_string) - return substitute(substitute(a:input_string, "\n", '', 'g'), '(\s*\(.\{-}\)\s*', '\1', 'g') -endfunction - - -" Shortcut for g:RubyDebugger.logger.debug -function! s:log(string) - call g:RubyDebugger.logger.put(a:string) -endfunction - - -" Return match of inner tags without wrap tags. E.g.: -" mathes only -function! s:get_inner_tags(cmd) - return matchlist(a:cmd, '^<.\{-}>\(.\{-}\)<\/.\{-}>$') -endfunction - - -" Return Dict of attributes. -" E.g., from it returns -" {'name' : 'a', 'value' : 'b'} -function! s:get_tag_attributes(cmd) - let attributes = {} - let cmd = a:cmd - " Find type of used quotes (" or ') - let quote_match = matchlist(cmd, "\\w\\+=\\(.\\)") - let quote = empty(quote_match) ? "\"" : escape(quote_match[1], "'\"") - let pattern = "\\(\\w\\+\\)=" . quote . "\\(.\\{-}\\)" . quote - " Find every attribute and remove it from source string - let attrmatch = matchlist(cmd, pattern) - while !empty(attrmatch) - " Values of attributes can be escaped by HTML entities, unescape them - let attributes[attrmatch[1]] = s:unescape_html(attrmatch[2]) - " These symbols are interpretated as special, we need to escape them - let attrmatch[0] = escape(attrmatch[0], '[]~*\') - " Remove it from source string - let cmd = substitute(cmd, attrmatch[0], '', '') - " Find next attribute - let attrmatch = matchlist(cmd, pattern) - endwhile - return attributes -endfunction - - -" Unescape HTML entities -function! s:unescape_html(html) - let result = substitute(a:html, "&", "\\&", "g") - let result = substitute(result, """, "\"", "g") - let result = substitute(result, "<", "<", "g") - let result = substitute(result, ">", ">", "g") - return result -endfunction - - -function! s:quotify(exp) - let quoted = a:exp - let quoted = substitute(quoted, "\"", "\\\\\"", 'g') - return quoted -endfunction - - -" Get filename of current buffer -function! s:get_filename() - return expand("%:p") -endfunction - - -" Send message to debugger. This function should never be used explicitly, -" only through g:RubyDebugger.send_command function -function! s:send_message_to_debugger(message) - call s:log("Sending a message to ruby_debugger.rb: '" . a:message . "'") - if g:ruby_debugger_fast_sender - call s:log("Trying to use experimental 'fast_sender'") - let cmd = s:runtime_dir . "/bin/socket " . s:hostname . " " . s:debugger_port . " \"" . a:message . "\"" - call s:log("Executing command: " . cmd) - call system(cmd) - else - if g:ruby_debugger_builtin_sender - call s:log("Using Vim built-in Ruby to send message") -ruby << RUBY - require 'socket' - attempts = 0 - a = nil - host = VIM::evaluate("s:hostname") - port = VIM::evaluate("s:debugger_port") - message = VIM::evaluate("a:message").gsub("\\\"", '"') - begin - a = TCPSocket.open(host, port) - a.puts(message) - a.close - rescue Errno::ECONNREFUSED - attempts += 1 - if attempts < 400 - sleep 0.05 - retry - else - puts("#{host}:#{port} can not be opened") - exit - end - ensure - a.close if a && !a.closed? - end -RUBY - else - let script = "ruby -e \"require 'socket'; " - let script .= "attempts = 0; " - let script .= "a = nil; " - let script .= "begin; " - let script .= "a = TCPSocket.open('" . s:hostname . "', " . s:debugger_port . "); " - let script .= "a.puts(%q[" . substitute(substitute(a:message, '[', '\[', 'g'), ']', '\]', 'g') . "]);" - let script .= "a.close; " - let script .= "rescue Errno::ECONNREFUSED; " - let script .= "attempts += 1; " - let script .= "if attempts < 400; " - let script .= "sleep 0.05; " - let script .= "retry; " - let script .= "else; " - let script .= "puts('" . s:hostname . ":" . s:debugger_port . " can not be opened'); " - let script .= "exit; " - let script .= "end; " - let script .= "ensure; " - let script .= "a.close if a && !a.closed?; " - let script .= "end; \"" - call s:log("Using system-wide Ruby to send message, the command is: " . script) - let output = system(script) - call s:log("Command has returned following output: " . output) - if output =~ 'can not be opened' - call s:log("Can't send a message to rdebug - port is not opened") - endif - endif - endif -endfunction - - -function! s:unplace_sign_of_current_line() - if has("signs") - exe ":sign unplace " . s:current_line_sign_id - endif -endfunction - - -" Remove all variables of current line, remove current line sign. Usually it -" is needed before next/step/cont commands -function! s:clear_current_state() - call s:unplace_sign_of_current_line() - let g:RubyDebugger.variables = {} - let g:RubyDebugger.frames = [] - " Clear variables and frames window (just show our empty variables Dict) - if s:variables_window.is_open() - call s:variables_window.open() - endif - if s:frames_window.is_open() - call s:frames_window.open() - endif -endfunction - - -" Open given file and jump to given line -" (stolen from NERDTree) -function! s:jump_to_file(file, line) - "if the file is already open in this tab then just stick the cursor in it - let window_number = bufwinnr('^' . a:file . '$') - if window_number != -1 - exe window_number . "wincmd w" - else - " Check if last accessed window is usable to use it - " Usable window - not quickfix, explorer, modified, etc - if !s:is_window_usable(winnr("#")) - exe s:first_normal_window() . "wincmd w" - else - " If it is usable, jump to it - exe 'wincmd p' - endif - exe "edit " . a:file - endif - exe "normal " . a:line . "G" -endfunction - - -" Return 1 if window is usable (not quickfix, explorer, modified, only one -" window, ...) -function! s:is_window_usable(winnumber) - "If there is only one window (winnr("$") - windows count) - if winnr("$") ==# 1 - return 0 - endif - - " Current window number - let oldwinnr = winnr() - - " Switch to given window and check it - exe a:winnumber . "wincmd p" - let specialWindow = getbufvar("%", '&buftype') != '' || getwinvar('%', '&previewwindow') - let modified = &modified - - exe oldwinnr . "wincmd p" - - "if it is a special window, e.g. quickfix or another explorer plugin - if specialWindow - return 0 - endif - - if &hidden - return 1 - endif - - " If this window is modified, but there is another opened window with - " current file, return 1. Otherwise - 0 - return !modified || s:buf_in_windows(winbufnr(a:winnumber)) >= 2 -endfunction - - -" Determine the number of windows open to this buffer number. -function! s:buf_in_windows(buffer_number) - let count = 0 - let window_number = 1 - while 1 - let buffer_number = winbufnr(window_number) - if buffer_number < 0 - break - endif - if buffer_number ==# a:buffer_number - let count = count + 1 - endif - let window_number = window_number + 1 - endwhile - - return count -endfunction - - -" Find first 'normal' window (not quickfix, explorer, etc) -function! s:first_normal_window() - let i = 1 - while i <= winnr("$") - let bnum = winbufnr(i) - if bnum != -1 && getbufvar(bnum, '&buftype') ==# '' && !getwinvar(i, '&previewwindow') - return i - endif - let i += 1 - endwhile - return -1 -endfunction - -" *** Queue class (start) - -let s:Queue = {} - -" ** Public methods - -" Constructor of new queue. -function! s:Queue.new() dict - let var = copy(self) - let var.queue = [] - let var.after = "" - return var -endfunction - - -" Execute next command in the queue and remove it from queue -function! s:Queue.execute() dict - if !empty(self.queue) - call s:log("Executing queue") - let message = join(self.queue, s:separator) - call self.empty() - call g:RubyDebugger.send_command(message) - endif -endfunction - - -" Execute 'after' hook only if queue is empty -function! s:Queue.after_hook() dict - if self.after != "" && empty(self.queue) - call self.after() - endif -endfunction - - -function! s:Queue.add(element) dict - call s:log("Adding '" . a:element . "' to queue") - call add(self.queue, a:element) -endfunction - - -function! s:Queue.empty() dict - let self.queue = [] -endfunction - - -" *** Queue class (end) - - - - -" *** Public interface (start) - -let RubyDebugger = { 'commands': {}, 'variables': {}, 'settings': {}, 'breakpoints': [], 'frames': [], 'exceptions': [] } -let g:RubyDebugger.queue = s:Queue.new() - - -" Run debugger server. It takes one optional argument with path to debugged -" ruby script ('script/server webrick' by default) -function! RubyDebugger.start(...) dict - call s:log("Executing :Rdebugger...") - let g:RubyDebugger.server = s:Server.new(s:hostname, s:rdebug_port, s:debugger_port, s:runtime_dir, s:tmp_file, s:server_output_file) - let script_string = a:0 && !empty(a:1) ? a:1 : g:ruby_debugger_default_script - let params = a:0 && a:0 > 1 && !empty(a:2) ? a:2 : [] - echo "Loading debugger..." - call g:RubyDebugger.server.start(s:get_escaped_absolute_path(script_string), params) - - let g:RubyDebugger.exceptions = [] - for breakpoint in g:RubyDebugger.breakpoints - call g:RubyDebugger.queue.add(breakpoint.command()) - endfor - call g:RubyDebugger.queue.add('start') - echo "Debugger started" - call g:RubyDebugger.queue.execute() -endfunction - - -" Stop running server. -function! RubyDebugger.stop() dict - if has_key(g:RubyDebugger, 'server') - call g:RubyDebugger.server.stop() - endif -endfunction - -function! RubyDebugger.is_running() - if has_key(g:RubyDebugger, 'server') - return g:RubyDebugger.server.is_running() - endif - return 0 -endfunction - -" This function receives commands from the debugger. When ruby_debugger.rb -" gets output from rdebug-ide, it writes it to the special file and 'kick' -" the plugin by remotely calling RubyDebugger.receive_command(), e.g.: -" vim --servername VIM --remote-send 'call RubyDebugger.receive_command()' -" That's why +clientserver is required -" This function analyzes the special file and gives handling to right command -function! RubyDebugger.receive_command() dict - let file_contents = join(readfile(s:tmp_file), "") - call s:log("Received command: " . file_contents) - let commands = split(file_contents, s:separator) - for cmd in commands - if !empty(cmd) - if match(cmd, '') != -1 - call g:RubyDebugger.commands.set_variables(cmd) - elseif match(cmd, '') != -1 - call g:RubyDebugger.commands.error(cmd) - elseif match(cmd, '') != -1 - call g:RubyDebugger.commands.message(cmd) - elseif match(cmd, '') != -1 - call g:RubyDebugger.commands.trace(cmd) - endif - endif - endfor - call g:RubyDebugger.queue.after_hook() - call g:RubyDebugger.queue.execute() -endfunction - - -function! RubyDebugger.send_command_wrapper(command) - call g:RubyDebugger.send_command(a:command) -endfunction - -" We set function this way, because we want have possibility to mock it by -" other function in tests -let RubyDebugger.send_command = function("send_message_to_debugger") - - -" Open variables window -function! RubyDebugger.open_variables() dict - call s:variables_window.toggle() - call s:log("Opened variables window") - call g:RubyDebugger.queue.execute() -endfunction - - -" Open breakpoints window -function! RubyDebugger.open_breakpoints() dict - call s:breakpoints_window.toggle() - call s:log("Opened breakpoints window") - call g:RubyDebugger.queue.execute() -endfunction - - -" Open frames window -function! RubyDebugger.open_frames() dict - call s:frames_window.toggle() - call s:log("Opened frames window") - call g:RubyDebugger.queue.execute() -endfunction - - -" Set/remove breakpoint at current position. If argument -" is given, it will set conditional breakpoint (argument is condition) -function! RubyDebugger.toggle_breakpoint(...) dict - let line = line(".") - let file = s:get_filename() - call s:log("Trying to toggle a breakpoint in the file " . file . ":" . line) - let existed_breakpoints = filter(copy(g:RubyDebugger.breakpoints), 'v:val.line == ' . line . ' && v:val.file == "' . escape(file, '\') . '"') - " If breakpoint with current file/line doesn't exist, create it. Otherwise - - " remove it - if empty(existed_breakpoints) - call s:log("There is no already set breakpoint, so create new one") - let breakpoint = s:Breakpoint.new(file, line) - call add(g:RubyDebugger.breakpoints, breakpoint) - call s:log("Added Breakpoint object to RubyDebugger.breakpoints array") - call breakpoint.send_to_debugger() - else - call s:log("There is already set breakpoint presented, so delete it") - let breakpoint = existed_breakpoints[0] - call filter(g:RubyDebugger.breakpoints, 'v:val.id != ' . breakpoint.id) - call s:log("Removed Breakpoint object from RubyDebugger.breakpoints array") - call breakpoint.delete() - endif - " Update info in Breakpoints window - if s:breakpoints_window.is_open() - call s:breakpoints_window.open() - exe "wincmd p" - endif - call g:RubyDebugger.queue.execute() -endfunction - - -" Remove all breakpoints -function! RubyDebugger.remove_breakpoints() dict - for breakpoint in g:RubyDebugger.breakpoints - call breakpoint.delete() - endfor - let g:RubyDebugger.breakpoints = [] - call g:RubyDebugger.queue.execute() -endfunction - - -" Eval the passed in expression -function! RubyDebugger.eval(exp) dict - let quoted = s:quotify(a:exp) - call g:RubyDebugger.queue.add("eval " . quoted) - call g:RubyDebugger.queue.execute() -endfunction - - -" Sets conditional breakpoint where cursor is placed -function! RubyDebugger.conditional_breakpoint(exp) dict - let line = line(".") - let file = s:get_filename() - let existed_breakpoints = filter(copy(g:RubyDebugger.breakpoints), 'v:val.line == ' . line . ' && v:val.file == "' . escape(file, '\') . '"') - " If breakpoint with current file/line doesn't exist, create it. Otherwise - - " remove it - if empty(existed_breakpoints) - echo "You can set condition only to already set breakpoints. Move cursor to set breakpoint and add condition" - else - let breakpoint = existed_breakpoints[0] - let quoted = s:quotify(a:exp) - call breakpoint.add_condition(quoted) - " Update info in Breakpoints window - if s:breakpoints_window.is_open() - call s:breakpoints_window.open() - exe "wincmd p" - endif - call g:RubyDebugger.queue.execute() - endif -endfunction - - -" Catch all exceptions with given name -function! RubyDebugger.catch_exception(exp) dict - if has_key(g:RubyDebugger, 'server') && g:RubyDebugger.server.is_running() - let quoted = s:quotify(a:exp) - let exception = s:Exception.new(quoted) - call add(g:RubyDebugger.exceptions, exception) - if s:breakpoints_window.is_open() - call s:breakpoints_window.open() - exe "wincmd p" - endif - call g:RubyDebugger.queue.execute() - else - echo "Sorry, but you can set Exceptional Breakpoints only with running debugger" - endif -endfunction - - -" Next -function! RubyDebugger.next() dict - call g:RubyDebugger.queue.add("next") - call s:clear_current_state() - call s:log("Step over") - call g:RubyDebugger.queue.execute() -endfunction - - -" Step -function! RubyDebugger.step() dict - call g:RubyDebugger.queue.add("step") - call s:clear_current_state() - call s:log("Step into") - call g:RubyDebugger.queue.execute() -endfunction - - -" Finish -function! RubyDebugger.finish() dict - call g:RubyDebugger.queue.add("finish") - call s:clear_current_state() - call s:log("Step out") - call g:RubyDebugger.queue.execute() -endfunction - - -" Continue -function! RubyDebugger.continue() dict - call g:RubyDebugger.queue.add("cont") - call s:clear_current_state() - call s:log("Continue") - call g:RubyDebugger.queue.execute() -endfunction - - -" Exit -function! RubyDebugger.exit() dict - call g:RubyDebugger.queue.add("exit") - call s:clear_current_state() - call g:RubyDebugger.queue.execute() -endfunction - - -" Show output log of Ruby script -function! RubyDebugger.show_log() dict - exe "view " . s:server_output_file - setlocal autoread - " Per gorkunov's request - setlocal wrap - setlocal nonumber - if exists(":AnsiEsc") - exec ":AnsiEsc" - endif -endfunction - - -" Debug current opened test -function! RubyDebugger.run_test(...) dict - let file = s:get_filename() - if file =~ '_spec\.rb$' - let line = a:0 && a:0 > 0 && !empty(a:1) ? a:1 : " " - call g:RubyDebugger.start(g:ruby_debugger_spec_path . ' ' . file . line) - elseif file =~ '\.feature$' - call g:RubyDebugger.start(g:ruby_debugger_cucumber_path . ' ' . file) - elseif file =~ '_test\.rb$' - call g:RubyDebugger.start(file, ['-Itest']) - endif -endfunction - - -" *** Public interface (end) - - - - -" *** RubyDebugger Commands (what debugger returns) - - -" -" -" Jump to file/line where execution was suspended, set current line sign and get local variables -function! RubyDebugger.commands.jump_to_breakpoint(cmd) dict - let attrs = s:get_tag_attributes(a:cmd) - call s:jump_to_file(attrs.file, attrs.line) - call s:log("Jumped to breakpoint " . attrs.file . ":" . attrs.line) - - if has("signs") - exe ":sign place " . s:current_line_sign_id . " line=" . attrs.line . " name=current_line file=" . attrs.file - endif -endfunction - - -" -" Show message error and jump to given file/line -function! RubyDebugger.commands.handle_exception(cmd) dict - let message_match = matchlist(a:cmd, 'message="\(.\{-}\)"') - call g:RubyDebugger.commands.jump_to_breakpoint(a:cmd) - echo "Exception message: " . s:unescape_html(message_match[1]) -endfunction - - -" -" Confirm setting of exception catcher -function! RubyDebugger.commands.set_exception(cmd) dict - let attrs = s:get_tag_attributes(a:cmd) - call s:log("Exception successfully set: " . attrs.exception) -endfunction - - -" -" Add debugger info to breakpoints (pid of debugger, debugger breakpoint's id) -" Assign rest breakpoints to debugger recursively, if there are breakpoints -" from old server runnings or not assigned breakpoints (e.g., if you at first -" set some breakpoints, and then run the debugger by :Rdebugger) -function! RubyDebugger.commands.set_breakpoint(cmd) - call s:log("Received the breakpoint message, will add PID and number of breakpoint to the Breakpoint object") - let attrs = s:get_tag_attributes(a:cmd) - let file_match = matchlist(attrs.location, '\(.*\):\(.*\)') - let pid = g:RubyDebugger.server.rdebug_pid - - " Find added breakpoint in array and assign debugger's info to it - for breakpoint in g:RubyDebugger.breakpoints - if expand(breakpoint.file) == expand(file_match[1]) && expand(breakpoint.line) == expand(file_match[2]) - call s:log("Found the Breakpoint object for " . breakpoint.file . ":" . breakpoint.line) - let breakpoint.debugger_id = attrs.no - let breakpoint.rdebug_pid = pid - call s:log("Added id: " . breakpoint.debugger_id . ", PID:" . breakpoint.rdebug_pid . " to Breakpoint") - if has_key(breakpoint, 'condition') - call breakpoint.add_condition(breakpoint.condition) - endif - endif - endfor - - call s:log("Breakpoint is set: " . file_match[1] . ":" . file_match[2]) - call g:RubyDebugger.queue.execute() -endfunction - - -" -" -" -" Assign list of got variables to parent variable and (optionally) show them -function! RubyDebugger.commands.set_variables(cmd) - let tags = s:get_tags(a:cmd) - let list_of_variables = [] - - " Create hash from list of tags - for tag in tags - let attrs = s:get_tag_attributes(tag) - let variable = s:Var.new(attrs) - call add(list_of_variables, variable) - endfor - - " If there is no variables, create unnamed root variable. Local variables - " will be chilren of this variable - if g:RubyDebugger.variables == {} - let g:RubyDebugger.variables = s:VarParent.new({'hasChildren': 'true'}) - let g:RubyDebugger.variables.is_open = 1 - let g:RubyDebugger.variables.children = [] - endif - - " If g:RubyDebugger.current_variable exists, then it contains parent - " variable of got subvariables. Assign them to it. - if has_key(g:RubyDebugger, 'current_variable') - let variable = g:RubyDebugger.current_variable - if variable != {} - call variable.add_childs(list_of_variables) - call s:log("Opening child variable: " . variable.attributes.objectId) - " Variables Window is always open if we got subvariables - call s:variables_window.open() - else - call s:log("Can't found variable") - endif - unlet g:RubyDebugger.current_variable - else - " Otherwise, assign them to unnamed root variable - if g:RubyDebugger.variables.children == [] - call g:RubyDebugger.variables.add_childs(list_of_variables) - call s:log("Initializing local variables") - if s:variables_window.is_open() - " show variables only if Variables Window is open - call s:variables_window.open() - endif - endif - endif - -endfunction - - -" -" Just show result of evaluation -function! RubyDebugger.commands.eval(cmd) - " rdebug-ide-gem doesn't escape attributes of tag properly, so we should not - " use usual attribute extractor here... - let match = matchlist(a:cmd, "") - echo "Evaluated expression:\n" . s:unescape_html(match[1]) ."\nResulted value is:\n" . match[2] . "\n" -endfunction - - -" -" Just show exception message -function! RubyDebugger.commands.processing_exception(cmd) - let attrs = s:get_tag_attributes(a:cmd) - let message = "RubyDebugger Exception, type: " . attrs.type . ", message: " . attrs.message - echo message - call s:log(message) -endfunction - - -" -" -" -" -" Assign all frames, fill Frames window by them -function! RubyDebugger.commands.trace(cmd) - let tags = s:get_tags(a:cmd) - let list_of_frames = [] - - " Create hash from list of tags - for tag in tags - let attrs = s:get_tag_attributes(tag) - let frame = s:Frame.new(attrs) - call add(list_of_frames, frame) - endfor - - let g:RubyDebugger.frames = list_of_frames - - if s:frames_window.is_open() - " show backtrace only if Backtrace Window is open - call s:frames_window.open() - endif -endfunction - - -" Error -" Just show error -function! RubyDebugger.commands.error(cmd) - let error_match = s:get_inner_tags(a:cmd) - if !empty(error_match) - let error = error_match[1] - echo "RubyDebugger Error: " . error - call s:log("Got error: " . error) - endif -endfunction - - -" Message -" Just show message -function! RubyDebugger.commands.message(cmd) - let message_match = s:get_inner_tags(a:cmd) - if !empty(message_match) - let message = message_match[1] - echo "RubyDebugger Message: " . message - call s:log("Got message: " . message) - endif -endfunction - - -" *** End of debugger Commands - - - -" *** Window class (start). Abstract Class for creating window. -" Must be inherited. Mostly, stolen from the NERDTree. - -let s:Window = {} -let s:Window['next_buffer_number'] = 1 -let s:Window['position'] = 'botright' -let s:Window['size'] = 10 - -" ** Public methods - -" Constructs new window -function! s:Window.new(name, title) dict - let new_variable = copy(self) - let new_variable.name = a:name - let new_variable.title = a:title - return new_variable -endfunction - - -" Clear all data from window -function! s:Window.clear() dict - silent 1,$delete _ -endfunction - - -" Close window -function! s:Window.close() dict - if !self.is_open() - throw "RubyDebug: Window " . self.name . " is not open" - endif - - if winnr("$") != 1 - call self.focus() - close - exe "wincmd p" - else - " If this is only one window, just quit - :q - endif - call s:log("Closed window with name: " . self.name) -endfunction - - -" Get window number -function! s:Window.get_number() dict - if self._exist_for_tab() - return bufwinnr(self._buf_name()) - else - return -1 - endif -endfunction - - -" Display data to the window -function! s:Window.display() - call s:log("Start displaying data in window with name: " . self.name) - call self.focus() - setlocal modifiable - - let current_line = line(".") - let current_column = col(".") - let top_line = line("w0") - - call self.clear() - - call self._insert_data() - call self._restore_view(top_line, current_line, current_column) - - setlocal nomodifiable - call s:log("Complete displaying data in window with name: " . self.name) -endfunction - - -" Put cursor to the window -function! s:Window.focus() dict - exe self.get_number() . " wincmd w" - call s:log("Set focus to window with name: " . self.name) -endfunction - - -" Return 1 if window is opened -function! s:Window.is_open() dict - return self.get_number() != -1 -endfunction - - -" Open window and display data (stolen from NERDTree) -function! s:Window.open() dict - if !self.is_open() - " create the window - silent exec self.position . ' ' . self.size . ' new' - - if !self._exist_for_tab() - " If the window is not opened/exists, create new - call self._set_buf_name(self._next_buffer_name()) - silent! exec "edit " . self._buf_name() - " This function does not exist in Window class and should be declared in - " descendants - call self.bind_mappings() - else - " Or just jump to opened buffer - silent! exec "buffer " . self._buf_name() - endif - - " set buffer options - setlocal winfixheight - setlocal noswapfile - setlocal buftype=nofile - setlocal nowrap - setlocal foldcolumn=0 - setlocal nobuflisted - setlocal nospell - setlocal nolist - iabc - setlocal cursorline - setfiletype ruby_debugger_window - call s:log("Opened window with name: " . self.name) - endif - - if has("syntax") && exists("g:syntax_on") && !has("syntax_items") - call self.setup_syntax_highlighting() - endif - - call self.display() -endfunction - - -" Open/close window -function! s:Window.toggle() dict - call s:log("Toggling window with name: " . self.name) - if self._exist_for_tab() && self.is_open() - call self.close() - else - call self.open() - end -endfunction - - -" ** Private methods - - -" Return buffer name, that is stored in tab variable -function! s:Window._buf_name() dict - return t:window_{self.name}_buf_name -endfunction - - -" Return 1 if the window exists in current tab -function! s:Window._exist_for_tab() dict - return exists("t:window_" . self.name . "_buf_name") -endfunction - - -" Insert data to the window -function! s:Window._insert_data() dict - let old_p = @p - " Put data to the register and then show it by 'put' command - let @p = self.render() - silent exe "normal \"pP" - let @p = old_p - call s:log("Inserted data to window with name: " . self.name) -endfunction - - -" Calculate correct name for the window -function! s:Window._next_buffer_name() dict - let name = self.name . s:Window.next_buffer_number - let s:Window.next_buffer_number += 1 - return name -endfunction - - -" Restore the view -function! s:Window._restore_view(top_line, current_line, current_column) dict - let old_scrolloff=&scrolloff - let &scrolloff=0 - call cursor(a:top_line, 1) - normal! zt - call cursor(a:current_line, a:current_column) - let &scrolloff = old_scrolloff - call s:log("Restored view of window with name: " . self.name) -endfunction - - -function! s:Window._set_buf_name(name) dict - let t:window_{self.name}_buf_name = a:name -endfunction - - -" *** Window class (end) - - -" *** WindowVariables class (start) - -" Inherits variables window from abstract window class -let s:WindowVariables = copy(s:Window) - -" ** Public methods - -function! s:WindowVariables.bind_mappings() - nnoremap <2-leftmouse> :call window_variables_activate_node() - nnoremap o :call window_variables_activate_node()" -endfunction - - -" Returns string that contains all variables (for Window.display()) -function! s:WindowVariables.render() dict - let variables = self.title . "\n" - let variables .= (g:RubyDebugger.variables == {} ? '' : g:RubyDebugger.variables.render()) - return variables -endfunction - - -" TODO: Is there some way to call s:WindowVariables.activate_node from mapping -" command? -" Expand/collapse variable under cursor -function! s:window_variables_activate_node() - let variable = s:Var.get_selected() - if variable != {} && variable.type == "VarParent" - if variable.is_open - call variable.close() - else - call variable.open() - endif - endif - call g:RubyDebugger.queue.execute() -endfunction - - -" Add syntax highlighting -function! s:WindowVariables.setup_syntax_highlighting() - execute "syn match rdebugTitle #" . self.title . "#" - - syn match rdebugPart #[| `]\+# - syn match rdebugPartFile #[| `]\+-# contains=rdebugPart nextgroup=rdebugChild contained - syn match rdebugChild #.\{-}\t# nextgroup=rdebugType contained - - syn match rdebugClosable #[| `]\+\~# contains=rdebugPart nextgroup=rdebugParent contained - syn match rdebugOpenable #[| `]\++# contains=rdebugPart nextgroup=rdebugParent contained - syn match rdebugParent #.\{-}\t# nextgroup=rdebugType contained - - syn match rdebugType #.\{-}\t# nextgroup=rdebugValue contained - syn match rdebugValue #.*\t#he=e-1 nextgroup=rdebugId contained - syn match rdebugId #.*# contained - - syn match rdebugParentLine '[| `]\+[+\~].*' contains=rdebugClosable,rdebugOpenable transparent - syn match rdebugChildLine '[| `]\+-.*' contains=rdebugPartFile transparent - - hi def link rdebugTitle Identifier - hi def link rdebugClosable Type - hi def link rdebugOpenable Title - hi def link rdebugPart Special - hi def link rdebugPartFile Type - hi def link rdebugChild Normal - hi def link rdebugParent Directory - hi def link rdebugType Type - hi def link rdebugValue Special - hi def link rdebugId Ignore -endfunction - - -" *** WindowVariables class (end) - - - -" *** WindowBreakpoints class (start) - -" Inherits WindowBreakpoints from Window -let s:WindowBreakpoints = copy(s:Window) - -" ** Public methods - -function! s:WindowBreakpoints.bind_mappings() - nnoremap <2-leftmouse> :call window_breakpoints_activate_node() - nnoremap o :call window_breakpoints_activate_node() - nnoremap d :call window_breakpoints_delete_node() -endfunction - - -" Returns string that contains all breakpoints (for Window.display()) -function! s:WindowBreakpoints.render() dict - let breakpoints = "" - let breakpoints .= self.title . "\n" - for breakpoint in g:RubyDebugger.breakpoints - let breakpoints .= breakpoint.render() - endfor - let exceptions = map(copy(g:RubyDebugger.exceptions), 'v:val.render()') - let breakpoints .= "\nException breakpoints: " . join(exceptions, ", ") - return breakpoints -endfunction - - -" TODO: Is there some way to call s:WindowBreakpoints.activate_node from mapping -" command? -" Open breakpoint under cursor -function! s:window_breakpoints_activate_node() - let breakpoint = s:Breakpoint.get_selected() - if breakpoint != {} - call breakpoint.open() - endif -endfunction - - -" Delete breakpoint under cursor -function! s:window_breakpoints_delete_node() - let breakpoint = s:Breakpoint.get_selected() - if breakpoint != {} - call breakpoint.delete() - call filter(g:RubyDebugger.breakpoints, "v:val.id != " . breakpoint.id) - call s:breakpoints_window.open() - endif -endfunction - - -" Add syntax highlighting -function! s:WindowBreakpoints.setup_syntax_highlighting() dict - execute "syn match rdebugTitle #" . self.title . "#" - - syn match rdebugId "^\d\+\s" contained nextgroup=rdebugDebuggerId - syn match rdebugDebuggerId "\d*\s" contained nextgroup=rdebugFile - syn match rdebugFile ".*:" contained nextgroup=rdebugLine - syn match rdebugLine "\d\+" contained - - syn match rdebugWrapper "^\d\+.*" contains=rdebugId transparent - - hi def link rdebugId Directory - hi def link rdebugDebuggerId Type - hi def link rdebugFile Normal - hi def link rdebugLine Special -endfunction - - -" *** WindowBreakpoints class (end) - - - -" *** WindowFrames class (start) - -" Inherits WindowFrames from Window -let s:WindowFrames = copy(s:Window) - -" ** Public methods - -function! s:WindowFrames.bind_mappings() - nnoremap <2-leftmouse> :call window_frames_activate_node() - nnoremap o :call window_frames_activate_node() -endfunction - - -" Returns string that contains all frames (for Window.display()) -function! s:WindowFrames.render() dict - let frames = "" - let frames .= self.title . "\n" - for frame in g:RubyDebugger.frames - let frames .= frame.render() - endfor - return frames -endfunction - - -" Open frame under cursor -function! s:window_frames_activate_node() - let frame = s:Frame.get_selected() - if frame != {} - call frame.open() - endif -endfunction - - -" Add syntax highlighting -function! s:WindowFrames.setup_syntax_highlighting() dict - execute "syn match rdebugTitle #" . self.title . "#" - - syn match rdebugId "^\d\+\s" contained nextgroup=rdebugFile - syn match rdebugFile ".*:" contained nextgroup=rdebugLine - syn match rdebugLine "\d\+" contained - - syn match rdebugWrapper "^\d\+.*" contains=rdebugId transparent - - hi def link rdebugId Directory - hi def link rdebugFile Normal - hi def link rdebugLine Special -endfunction - - -" *** WindowFrames class (end) - - - - -" *** Var proxy class (start) - -let s:Var = { 'id' : 0 } - -" ** Public methods - -" This is a proxy method for creating new variable -function! s:Var.new(attrs) - if has_key(a:attrs, 'hasChildren') && a:attrs['hasChildren'] == 'true' - return s:VarParent.new(a:attrs) - else - return s:VarChild.new(a:attrs) - end -endfunction - - -" Get variable under cursor -function! s:Var.get_selected() - let line = getline(".") - " Get its id - it is last in the string - let match = matchlist(line, '.*\t\(\d\+\)$') - let id = get(match, 1) - if id - let variable = g:RubyDebugger.variables.find_variable({'id' : id}) - return variable - else - return {} - endif -endfunction - - -" *** Var proxy class (end) - - - -" *** VarChild class (start) - -let s:VarChild = {} - -" ** Public methods - -" Constructs new variable without childs -function! s:VarChild.new(attrs) - let new_variable = copy(self) - let new_variable.attributes = a:attrs - let new_variable.parent = {} - let new_variable.level = 0 - let new_variable.type = "VarChild" - let s:Var.id += 1 - let new_variable.id = s:Var.id - return new_variable -endfunction - - -" Renders data of the variable -function! s:VarChild.render() - return self._render(0, 0, [], len(self.parent.children) ==# 1) -endfunction - - -" VarChild can't be opened because it can't have children. But VarParent can -function! s:VarChild.open() - return 0 -endfunction - - -" VarChild can't be closed because it can't have children. But VarParent can -function! s:VarChild.close() - return 0 -endfunction - - -" VarChild can't be parent. But VarParent can. If Var have hasChildren == -" true, then it is parent -function! s:VarChild.is_parent() - return has_key(self.attributes, 'hasChildren') && get(self.attributes, 'hasChildren') ==# 'true' -endfunction - - -" Output format for Variables Window -function! s:VarChild.to_s() - return get(self.attributes, "name", "undefined") . "\t" . get(self.attributes, "type", "undefined") . "\t" . get(self.attributes, "value", "undefined") . "\t" . get(self, "id", "0") -endfunction - - -" Find and return variable by given Dict of attrs, e.g.: {'name' : 'var1'} -function! s:VarChild.find_variable(attrs) - if self._match_attributes(a:attrs) - return self - else - return {} - endif -endfunction - - -" Find and return array of variables that match given Dict of attrs -function! s:VarChild.find_variables(attrs) - let variables = [] - if self._match_attributes(a:attrs) - call add(variables, self) - endif - return variables -endfunction - - -" ** Private methods - - -" Recursive function, that renders Variable and all its childs (if they are -" presented). Stolen from NERDTree -function! s:VarChild._render(depth, draw_text, vertical_map, is_last_child) - let output = "" - if a:draw_text ==# 1 - let tree_parts = '' - - " get all the leading spaces and vertical tree parts for this line - if a:depth > 1 - for j in a:vertical_map[0:-2] - if j ==# 1 - let tree_parts = tree_parts . '| ' - else - let tree_parts = tree_parts . ' ' - endif - endfor - endif - - " get the last vertical tree part for this line which will be different - " if this node is the last child of its parent - if a:is_last_child - let tree_parts = tree_parts . '`' - else - let tree_parts = tree_parts . '|' - endif - - " smack the appropriate dir/file symbol on the line before the file/dir - " name itself - if self.is_parent() - if self.is_open - let tree_parts = tree_parts . '~' - else - let tree_parts = tree_parts . '+' - endif - else - let tree_parts = tree_parts . '-' - endif - let line = tree_parts . self.to_s() - let output = output . line . "\n" - - endif - - if self.is_parent() && self.is_open - if len(self.children) > 0 - - " draw all the nodes children except the last - let last_index = len(self.children) - 1 - if last_index > 0 - for i in self.children[0:last_index - 1] - let output = output . i._render(a:depth + 1, 1, add(copy(a:vertical_map), 1), 0) - endfor - endif - - " draw the last child, indicating that it IS the last - let output = output . self.children[last_index]._render(a:depth + 1, 1, add(copy(a:vertical_map), 0), 1) - - endif - endif - - return output - -endfunction - - -" Return 1 if *all* given attributes (pairs key/value) match to current -" variable -function! s:VarChild._match_attributes(attrs) - let conditions = 1 - for attr in keys(a:attrs) - if has_key(self.attributes, attr) - " If current key is contained in attributes of variable (they were - " attributes in tag, then trying to match there. - let conditions = conditions && self.attributes[attr] == a:attrs[attr] - elseif has_key(self, attr) - " Otherwise, if current key is contained in auxiliary attributes of the - " variable, trying to match there - let conditions = conditions && self[attr] == a:attrs[attr] - else - " Otherwise, this variable is not match - let conditions = 0 - break - endif - endfor - return conditions -endfunction - - -" *** VarChild class (end) - - - - -" *** VarParent class (start) - -" Inherits VarParent from VarChild -let s:VarParent = copy(s:VarChild) - -" ** Public methods - - -" Initializes new variable with childs -function! s:VarParent.new(attrs) - if !has_key(a:attrs, 'hasChildren') || a:attrs['hasChildren'] != 'true' - throw "RubyDebug: VarParent must be initialized with hasChildren = true" - endif - let new_variable = copy(self) - let new_variable.attributes = a:attrs - let new_variable.parent = {} - let new_variable.is_open = 0 - let new_variable.level = 0 - let new_variable.children = [] - let new_variable.type = "VarParent" - let s:Var.id += 1 - let new_variable.id = s:Var.id - return new_variable -endfunction - - -" Open variable, init its children and display them -function! s:VarParent.open() - let self.is_open = 1 - call self._init_children() - return 0 -endfunction - - -" Close variable and display it -function! s:VarParent.close() - let self.is_open = 0 - call s:variables_window.display() - if has_key(g:RubyDebugger, "current_variable") - unlet g:RubyDebugger.current_variable - endif - return 0 -endfunction - - -" Renders data of the variable -function! s:VarParent.render() - return self._render(0, 0, [], len(self.children) ==# 1) -endfunction - - - -" Add childs to the variable. You always should use this method instead of -" explicit assigning to children property (like 'add(self.children, variables)') -function! s:VarParent.add_childs(childs) - " If children are given by array, extend self.children by this array - if type(a:childs) == type([]) - for child in a:childs - let child.parent = self - let child.level = self.level + 1 - endfor - call extend(self.children, a:childs) - else - " Otherwise, add child to self.children - let a:childs.parent = self - let child.level = self.level + 1 - call add(self.children, a:childs) - end -endfunction - - -" Find and return variable by given Dict of attrs, e.g.: {'name' : 'var1'} -" If current variable doesn't match these attributes, try to find in children -function! s:VarParent.find_variable(attrs) - if self._match_attributes(a:attrs) - return self - else - for child in self.children - let result = child.find_variable(a:attrs) - if result != {} - return result - endif - endfor - endif - return {} -endfunction - - -" Find and return array of variables that match given Dict of attrs. -" Try to match current variable and its children -function! s:VarParent.find_variables(attrs) - let variables = [] - if self._match_attributes(a:attrs) - call add(variables, self) - endif - for child in self.children - call extend(variables, child.find_variables(a:attrs)) - endfor - return variables -endfunction - - -" ** Private methods - - -" Update children of the variable -function! s:VarParent._init_children() - " Remove all the current child nodes - let self.children = [] - - " Get children - if has_key(self.attributes, 'objectId') - let g:RubyDebugger.current_variable = self - call g:RubyDebugger.queue.add('var instance ' . self.attributes.objectId) - endif - -endfunction - - -" *** VarParent class (end) - - - -" *** Logger class (start) - -let s:Logger = {} - -function! s:Logger.new(file) - let new_variable = copy(self) - let new_variable.file = a:file - call writefile([], new_variable.file) - return new_variable -endfunction - - -" Log datetime and then message. It logs only if debug mode is enabled -" TODO It outputs a bunch of spaces at the front of the entry - fix that. -function! s:Logger.put(string) dict - if g:ruby_debugger_debug_mode - let string = 'Vim plugin, ' . strftime("%H:%M:%S") . ': ' . a:string - exec 'redir >> ' . g:RubyDebugger.logger.file - silent call s:Logger.silent_echo(s:strip(string)) - exec 'redir END' - endif -endfunction - -function! s:Logger.silent_echo(string) - echo a:string -endfunction - -" *** Logger class (end) -" -" - -" *** Breakpoint class (start) - -let s:Breakpoint = { 'id': 0 } - -" ** Public methods - -" Constructor of new brekpoint. Create new breakpoint and set sign. -function! s:Breakpoint.new(file, line) - let var = copy(self) - let var.file = a:file - let var.line = a:line - let s:Breakpoint.id += 1 - let var.id = s:Breakpoint.id - - call var._set_sign() - call s:log("Set breakpoint to: " . var.file . ":" . var.line) - return var -endfunction - - -" Destroyer of the breakpoint. It just sends commands to debugger and destroys -" sign, but you should manually remove it from breakpoints array -function! s:Breakpoint.delete() dict - call self._unset_sign() - call self._send_delete_to_debugger() -endfunction - - -" Add condition to breakpoint. If server is not running, just store it, it -" will be evaluated after starting the server -function! s:Breakpoint.add_condition(condition) dict - let self.condition = a:condition - if has_key(g:RubyDebugger, 'server') && g:RubyDebugger.server.is_running() && has_key(self, 'debugger_id') - call g:RubyDebugger.queue.add(self.condition_command()) - endif -endfunction - - - -" Send adding breakpoint message to debugger, if it is run -function! s:Breakpoint.send_to_debugger() dict - if has_key(g:RubyDebugger, 'server') && g:RubyDebugger.server.is_running() - call s:log("Server is running, so add command to Queue") - call g:RubyDebugger.queue.add(self.command()) - endif -endfunction - - -" Command for setting breakpoint (e.g.: 'break /path/to/file:23') -function! s:Breakpoint.command() dict - return 'break ' . self.file . ':' . self.line -endfunction - - -" Command for adding condition to breakpoin (e.g.: 'condition 1 x>5') -function! s:Breakpoint.condition_command() dict - return 'condition ' . self.debugger_id . ' ' . self.condition -endfunction - - -" Find and return breakpoint under cursor -function! s:Breakpoint.get_selected() dict - let line = getline(".") - let match = matchlist(line, '^\(\d\+\)') - let id = get(match, 1) - let breakpoints = filter(copy(g:RubyDebugger.breakpoints), "v:val.id == " . id) - if !empty(breakpoints) - return breakpoints[0] - else - return {} - endif -endfunction - - -" Output format for Breakpoints Window -function! s:Breakpoint.render() dict - let output = self.id . " " . (exists("self.debugger_id") ? self.debugger_id : '') . " " . self.file . ":" . self.line - if exists("self.condition") - let output .= " " . self.condition - endif - return output . "\n" -endfunction - - -" Open breakpoint in existed/new window -function! s:Breakpoint.open() dict - call s:jump_to_file(self.file, self.line) -endfunction - - -" ** Private methods - - -function! s:Breakpoint._set_sign() dict - if has("signs") - exe ":sign place " . self.id . " line=" . self.line . " name=breakpoint file=" . self.file - endif -endfunction - - -function! s:Breakpoint._unset_sign() dict - if has("signs") - exe ":sign unplace " . self.id - endif -endfunction - - -" Send deleting breakpoint message to debugger, if it is run -" (e.g.: 'delete 5') -function! s:Breakpoint._send_delete_to_debugger() dict - if has_key(g:RubyDebugger, 'server') && g:RubyDebugger.server.is_running() - let message = 'delete ' . self.debugger_id - call g:RubyDebugger.queue.add(message) - endif -endfunction - - -" *** Breakpoint class (end) - -" *** Exception class (start) -" These are ruby exceptions we catch with 'catch Exception' command -" (:RdbCatch) - -let s:Exception = { } - -" ** Public methods - -" Constructor of new exception. -function! s:Exception.new(name) - let var = copy(self) - let var.name = a:name - call s:log("Trying to set exception: " . var.name) - call g:RubyDebugger.queue.add(var.command()) - return var -endfunction - - -" Command for setting exception (e.g.: 'catch NameError') -function! s:Exception.command() dict - return 'catch ' . self.name -endfunction - - -" Output format for Breakpoints Window -function! s:Exception.render() dict - return self.name -endfunction - -" *** Exception class (end) - - - - -" *** Frame class (start) - -let s:Frame = { } - -" ** Public methods - -" Constructor of new frame. -" Create new frame and set sign to it. -function! s:Frame.new(attrs) - let var = copy(self) - let var.no = a:attrs.no - let var.file = a:attrs.file - let var.line = a:attrs.line - if has_key(a:attrs, 'current') - let var.current = (a:attrs.current == 'true') - else - let var.current = 0 - endif - "let s:sign_id += 1 - "let var.sign_id = s:sign_id - "call var._set_sign() - return var -endfunction - - -" Find and return frame under cursor -function! s:Frame.get_selected() dict - let line = getline(".") - let match = matchlist(line, '^\(\d\+\)') - let no = get(match, 1) - let frames = filter(copy(g:RubyDebugger.frames), "v:val.no == " . no) - if !empty(frames) - return frames[0] - else - return {} - endif -endfunction - - -" Output format for Frame Window -function! s:Frame.render() dict - return self.no . (self.current ? ' Current' : ''). " " . self.file . ":" . self.line . "\n" -endfunction - - -" Open frame in existed/new window -function! s:Frame.open() dict - call s:jump_to_file(self.file, self.line) -endfunction - - -" ** Private methods - -function! s:Frame._set_sign() dict - if has("signs") - exe ":sign place " . self.sign_id . " line=" . self.line . " name=frame file=" . self.file - endif -endfunction - - -function! s:Frame._unset_sign() dict - if has("signs") - exe ":sign unplace " . self.sign_id - endif -endfunction - - -" *** Frame class (end) - - - -" *** Server class (start) - -let s:Server = {} - -" ** Public methods - -" Constructor of new server. Just inits it, not runs -function! s:Server.new(hostname, rdebug_port, debugger_port, runtime_dir, tmp_file, output_file) dict - let var = copy(self) - let var.hostname = a:hostname - let var.rdebug_port = a:rdebug_port - let var.debugger_port = a:debugger_port - let var.runtime_dir = a:runtime_dir - let var.tmp_file = a:tmp_file - let var.output_file = a:output_file - call s:log("Initializing Server object, with variables: hostname: " . var.hostname . ", rdebug_port: " . var.rdebug_port . ", debugger_port: " . var.debugger_port . ", runtime_dir: " . var.runtime_dir . ", tmp_file: " . var.tmp_file . ", output_file: " . var.output_file) - return var -endfunction - - -" Start the server. It will kill any listeners on given ports before. -function! s:Server.start(script, params) dict - call s:log("Starting Server, command: " . a:script) - call s:log("Trying to kill all old servers first") - call self._stop_server(self.rdebug_port) - call self._stop_server(self.debugger_port) - call s:log("Servers are killed, trying to start new servers") - " Remove leading and trailing quotes - let script_name = substitute(a:script, "\\(^['\"]\\|['\"]$\\)", '', 'g') - let rdebug = 'rdebug-ide ' . join(a:params, ' ') . ' -p ' . self.rdebug_port . ' -- ' . script_name - let os = has("win32") || has("win64") ? 'win' : 'posix' - " Example - ruby ~/.vim/bin/ruby_debugger.rb 39767 39768 vim VIM /home/anton/.vim/tmp/ruby_debugger posix - let debugger_parameters = ' ' . self.hostname . ' ' . self.rdebug_port . ' ' . self.debugger_port - let debugger_parameters .= ' ' . g:ruby_debugger_progname . ' ' . v:servername . ' "' . self.tmp_file - let debugger_parameters .= '" ' . os . ' ' . g:ruby_debugger_debug_mode . ' ' . s:logger_file - - " Start in background - if has("win32") || has("win64") - silent exe '! start ' . rdebug - let debugger = 'ruby "' . expand(self.runtime_dir . "/bin/ruby_debugger.rb") . '"' . debugger_parameters - silent exe '! start ' . debugger - else - let cmd = rdebug . ' > ' . self.output_file . ' 2>&1 &' - call s:log("Executing command: ". cmd) - call system(cmd) - let debugger_cmd = 'ruby ' . expand(self.runtime_dir . "/bin/ruby_debugger.rb") . debugger_parameters . ' &' - call s:log("Executing command: ". debugger_cmd) - call system(debugger_cmd) - endif - - " Set PIDs of processes - call s:log("Now we need to store PIDs of servers, retrieving them: ") - let self.rdebug_pid = self._get_pid(self.rdebug_port, 1) - let self.debugger_pid = self._get_pid(self.debugger_port, 1) - call s:log("Server PIDs are: rdebug-ide: " . self.rdebug_pid . ", ruby_debugger.rb: " . self.debugger_pid) - - call s:log("Debugger is successfully started") -endfunction - - -" Kill servers and empty PIDs -function! s:Server.stop() dict - call self._kill_process(self.rdebug_pid) - call self._kill_process(self.debugger_pid) - let self.rdebug_pid = "" - let self.debugger_pid = "" -endfunction - - -" Return 1 if processes with set PID exist. -function! s:Server.is_running() dict - return (self._get_pid(self.rdebug_port, 0) =~ '^\d\+$') && (self._get_pid(self.debugger_port, 0) =~ '^\d\+$') -endfunction - - -" ** Private methods - - -" Get PID of process, that listens given port on given host. If must_get_pid -" parameter is true, it will try to get PID for 10 seconds. -function! s:Server._get_pid(port, must_get_pid) - call s:log("Trying to find PID of process on " . a:port . " port, must_get_pid = " . a:must_get_pid) - let attempt = 0 - let pid = self._get_pid_attempt(a:port) - while a:must_get_pid && pid == "" && attempt < 1000 - sleep 10m - let attempt += 1 - let pid = self._get_pid_attempt(a:port) - endwhile - call s:log("PID - " . pid . ", found by " . attempt . " repeats") - return pid -endfunction - - -" Just try to get PID of process and return empty string if it was -" unsuccessful -function! s:Server._get_pid_attempt(port) - call s:log("Trying to find listener of port " . a:port) - if has("win32") || has("win64") - let netstat = system("netstat -anop tcp") - let pid_match = matchlist(netstat, ':' . a:port . '\s.\{-}LISTENING\s\+\(\d\+\)') - let pid = len(pid_match) > 0 ? pid_match[1] : "" - elseif executable('lsof') - let cmd = "lsof -i tcp:" . a:port . " | grep LISTEN | awk '{print $2}'" - call s:log("Executing command: " . cmd) - let pid = system(cmd) - let pid = substitute(pid, '\n', '', '') - else - let pid = "" - endif - call s:log("Found pid - " . pid) - return pid -endfunction - - -" Kill listener of given host/port -function! s:Server._stop_server(port) dict - let pid = self._get_pid(a:port, 0) - if pid =~ '^\d\+$' - call self._kill_process(pid) - endif -endfunction - - -" Kill process with given PID -function! s:Server._kill_process(pid) dict - let message = "Killing server with pid " . a:pid - call s:log(message) - echo message - let cmd = "ruby -e 'Process.kill(9," . a:pid . ")'" - call s:log("Executing command: " . cmd) - call system(cmd) - call s:log("Sleeping 100m...") - sleep 100m - call s:log("Killed server with pid: " . a:pid) -endfunction - - -" *** Server class (end) - - - -" *** Creating instances (start) - -if !exists("g:ruby_debugger_fast_sender") - let g:ruby_debugger_fast_sender = 0 -endif -if !exists("g:ruby_debugger_debug_mode") - let g:ruby_debugger_debug_mode = 0 -endif -" This variable allows to use built-in Ruby (see ':help ruby' and s:send_message_to_debugger function) -if !exists("g:ruby_debugger_builtin_sender") - if has("ruby") - let g:ruby_debugger_builtin_sender = 1 - else - let g:ruby_debugger_builtin_sender = 0 - endif -endif -if !exists("g:ruby_debugger_spec_path") - let g:ruby_debugger_spec_path = '/usr/bin/spec' -endif -if !exists("g:ruby_debugger_cucumber_path") - let g:ruby_debugger_cucumber_path = '/usr/bin/cucumber' -endif -if !exists("g:ruby_debugger_progname") - let g:ruby_debugger_progname = v:progname -endif -if !exists("g:ruby_debugger_default_script") - let g:ruby_debugger_default_script = 'script/server webrick' -endif -if !exists("g:ruby_debugger_no_maps") - let g:ruby_debugger_no_maps = 0 -endif - -" Creating windows -let s:variables_window = s:WindowVariables.new("variables", "Variables_Window") -let s:breakpoints_window = s:WindowBreakpoints.new("breakpoints", "Breakpoints_Window") -let s:frames_window = s:WindowFrames.new("frames", "Backtrace_Window") - -" Init logger. The plugin logs all its actions. If you have some troubles, -" this file can help -let RubyDebugger.logger = s:Logger.new(s:logger_file) -let s:variables_window.logger = RubyDebugger.logger -let s:breakpoints_window.logger = RubyDebugger.logger -let s:frames_window.logger = RubyDebugger.logger - -" *** Creating instances (end) - diff --git a/vim/bundle/vim-ruby-debugger/bin/ruby_debugger.rb b/vim/bundle/vim-ruby-debugger/bin/ruby_debugger.rb deleted file mode 100644 index ec5f4af..0000000 --- a/vim/bundle/vim-ruby-debugger/bin/ruby_debugger.rb +++ /dev/null @@ -1,190 +0,0 @@ -require 'benchmark' -require 'socket' - -class VimRubyDebugger - - def initialize(params) - @params = params - create_directory(@params[:messages_file]) - @rdebug = wait_for_opened_socket(@params[:host], @params[:rdebug_port]) - log("Start TCPServer with host: #{@params[:host]} and port: #{@params[:vim_ruby_debugger_port]}") - @vim_ruby_debugger = TCPServer.new(@params[:host], @params[:vim_ruby_debugger_port]) - @queue = [] - @result = [] - @separator = "++vim-ruby-debugger separator++" - run - rescue => error - log("ERROR!!!: #{error}\nBacktrace: #{error.backtrace}") - end - - private - - def wait_for_opened_socket(host, port) - attempts = 0 - begin - log("Starting to connect by TCPSocket with host: #{host} and port: #{port}") - socket = TCPSocket.open(host, port) - rescue Errno::ECONNREFUSED => msg - attempts += 1 - # If socket wasn't be opened for 20 seconds, exit - if attempts < 400 - sleep 0.05 - retry - else - raise Errno::ECONNREFUSED, "#{host}:#{port} wasn't be opened" - end - end - log("Connected with #{host}:#{port} by TCPSocket by #{attempts} repeats") - socket - end - - - def create_directory(file) - dir = File.dirname(file) - Dir.mkdir(dir) unless File.exist?(dir) && File.directory?(dir) - end - - - def run - t1 = Thread.new do - log("Start listening vim-ruby-debugger plugin") - while(session = @vim_ruby_debugger.accept) - input = session.gets - log("Received data from vim-ruby-debugger: #{input}") - @queue = input.split(@separator) - handle_queue - end - end - t2 = Thread.new do - log("Start listening rdebug-ide") - loop do - response = select([@rdebug], nil, nil) - output = read_socket(response, @rdebug) - log("Received data from rdebug-ide: #{output}") - @result << truncate_variables_values(output) - # If we stop at breakpoint, add taking of local variables into queue - stop_commands = [ '" : "") - sys_cmd = "#{@params[:vim_executable]} --servername #{@params[:vim_servername]} -u NONE -U NONE --remote-send \"#{starter}#{command}\"" - log("Executing command: #{sys_cmd}") - system(sys_cmd); - end - end - - - def truncate_variables_values(message) - if message.size > 30000 && message.include?("") - previous_position = 0 - while(start_position = message.index('value="', previous_position)) - start_position += 6 - end_position = message.index('"', start_position + 1) - length = end_position - start_position - if length > 30000 - value = message[(start_position + 1)..(start_position + 30000)] - value += " (the variable is truncated, its full length is #{length})" - else - value = message[(start_position + 1)..(end_position - 1)] - end - message = message[0..start_position] + value + message[end_position..-1] - previous_position = start_position - end - message - else - message - end - end - - - def have_unclosed_tag?(output) - start_match = output.match(/^<([a-zA-Z0-9\-_]+)>/) - if start_match - end_match = output.match(/<\/#{start_match[1]}>$/) - return end_match ? false : true - else - return false - end - end - - - def log(string) - if @params[:debug_mode] == '1' - File.open(@params[:logger_file], 'a') do |f| - # match vim redir style new lines, rather than trailing - f << "\nRuby_debugger.rb, #{Time.now.strftime("%H:%M:%S")} : #{string.chomp}" - end - end - end - -end - - -VimRubyDebugger.new( - :host => ARGV[0], - :rdebug_port => ARGV[1], - :vim_ruby_debugger_port => ARGV[2], - :vim_executable => ARGV[3], - :vim_servername => ARGV[4], - :messages_file => ARGV[5], - :os => ARGV[6], - :debug_mode => ARGV[7], - :logger_file => ARGV[8] -) diff --git a/vim/bundle/vim-ruby-debugger/doc/ruby_debugger.txt b/vim/bundle/vim-ruby-debugger/doc/ruby_debugger.txt deleted file mode 100644 index 0121d36..0000000 --- a/vim/bundle/vim-ruby-debugger/doc/ruby_debugger.txt +++ /dev/null @@ -1,357 +0,0 @@ -*ruby_debugger.txt* Plugin for debugging Ruby applications - -Author: Anton Astashov - |ruby-debugger-plugin-author| - -|ruby-debugger-introduction| Introduction and Feature Summary -|ruby-debugger-installation| Installation -|ruby-debugger-quickstart| QuickStart -|ruby-debugger-details| Some additional details about the plugin -|ruby-debugger-tests| Debugging of tests -|ruby-debugger-ruby19| Using the plugin with ruby 1.9 -|ruby-debugger-issues| Troubleshooting -|ruby-debugger-bugs| Bugreporting -|ruby-debugger-about| About - -This plugin is only available if 'compatible' is not set. -The plugin requires Vim to be compiled with +signs and +clientserver and Vim -version >= 7. To check it, run > - :echo has("signs") && has("clientserver") && v:version > 700 -Result should be equal to 1 -If you use Linux, make sure you have "lsof" installed. See > - http://en.wikipedia.org/wiki/Lsof - -Also, it requires ruby-debug-ide gem. To install it, run > - gem install ruby-debug-ide - -Please make sure, that vim/gvim, rdebug-ide and ruby directories are set in your -$PATH variable - -{Vi does not have any of this} - -============================================================================== -INTRODUCTION *ruby-debugger-introduction* *ruby-debugger* - -This plugin implements interactive Ruby debugger in Vim. - -1. It can debug any Ruby application (Rails, by default), using ruby-debug-ide -gem - -2. The debugger looks like in the Netbeans - you can go through the code, watch -variables, breakpoints in separate window, set and remove breakpoints. - -3. It supports command-line rdebug commands. E.g., you can you can execute > - :RdbCommand p User.all -in command line of VIM and it will display result like usual echo VIM command. - -============================================================================== -INSTALLATION *ruby-debugger-installation* - -Clone current version of the repo from GitHub: > - git clone git://github.com/astashov/vim-ruby-debugger.git -or if you don't have Git, download the archive from here: > - http://github.com/astashov/vim-ruby-debugger/tarball/master - -Then, copy the vim-ruby-debugger dir to the vim directory (to vimfiles -(Windows)or ~/.vim (everything else)). Or, if you use pathogen, copy the -vim-ruby-debugger dir to ~/.vim/bundle/vim-ruby-debugger. - -Then, run: > - :helptags ~/.vim/doc -for generating local tags file. - -Now you can use the > - :help ruby-debugger -and watch help file you just added. - -============================================================================== -QUICKSTART *ruby-debugger-quickstart* - -1. Run Vim. If you use gvim, it will automatically start the server, but if - you use vim, you need to set servername explicitly, e.g., > - vim --servername VIM - -2. Go to the directory with some your Rails 2 application. > - :cd ~/projects/rails - -3. Run Server with Debugger: > - :Rdebugger - -It will kill any listeners of ports 39767 and 39768 and run rdebug-ide and -~/.vim/bin/ruby_debugger.rb on these ports accordingly. - -3. Set breakpoint somewhere by b (usually, '\b'). You should see - "xx" symbol at the current line. - -4. Open page with the breakpoint in the browser. Vim should automatically set - its current line to breakpoint. - -5. After this, you can use commands: - * b - set breakpoint at current line - * v - open/close window with variables. You can expand/collapse - variables by 'o' in normal mode or left-mouse double-click - * m - open/close window with breakpoints. You can open file with - breakpoint by pressing 'o' or left-mouse double-click on it, - or delete the breakpoint by pressing 'd' on it. - * t - open/close window with backtrace. You can open file/line in - this window by pressing 'o' or left-mouse double-click on it - * n - step over - * s - step into - * f - step out - * c - continue - * d - remove all breakpoints - -6. To see when the ruby debugger is running, you can add the following function call -to your status line: - - set statusline=%{ruby_debugger#statusline()} - - When the debugger is running you'll see '[ruby debugger running]' - -============================================================================== -DETAILS *ruby-debugger-details* - -* Of course, you can set your own mappings instead of mine. For this, just - add this to your .vimrc and change keys for mapping: -> - map b :call g:RubyDebugger.toggle_breakpoint() - map v :call g:RubyDebugger.open_variables() - map m :call g:RubyDebugger.open_breakpoints() - map t :call g:RubyDebugger.open_frames() - map s :call g:RubyDebugger.step() - map f :call g:RubyDebugger.finish() - map n :call g:RubyDebugger.next() - map c :call g:RubyDebugger.continue() - map e :call g:RubyDebugger.exit() - map d :call g:RubyDebugger.remove_breakpoints() -> -* Standard output and errors (STDOUT and STDERR) of running script is -redirected to ~/.vim/tmp/ruby_debugger_output file (only for POSIX -systems - Linux, MacOS) - -* If you are using POSIX OS (Linux, MacOS), you can try fast C implementation - of message sender to debugger. For this, copy "socket" file from - additionals/bin/ to ~/.vim/bin/, add execution rights to it (chmod +x) - and add this string to your .vimrc: > - let g:ruby_debugger_fast_sender = 1 - -* You can specify path to Ruby (if it is not in your PATH environment or - you want to use specific version of Ruby) - -* To run some other Ruby application (not Rails), you should specify its - path as argument of Rdebugger command. E.g. > - :Rdebugger bla.rb -If your script receives arguments, quote it into single quotes: > - :Rdebugger '/path/to/bla.rb 1234 bla_bla' - -* You can specify default script which will be run when you specify - :Rdebugger without arguments. By default it is 'script/server webrick', - but you can change it (e.g. if you mostly use Rails 3) by adding such line - to your .vimrc: > - let g:ruby_debugger_default_script = 'script/rails s' - -* To run some rdebug command, use :RdbCommand. E.g.: > - :RdbCommand where - -* To eval some code, use :RdbEval. E.g.: > - :RdbEval u.name - :RdbEval app_config['settings'].map { |s| s.capitalize } - -* To add condition to some breakpoint, you can move cursor on the breakpoint, - and type command: > - :RdbCond condition -E.g.: > - :RdbCond current_user.name == "John" -Then, execution will be stopped on the breakpoint only if condition is true - -* To add exceptions catcher, use command: > - :RdbCatch NameOfException -This way, when exception is raised, debugger will catch it, jump to file/line -of the exception and you'll be allowed to watch variables, backtrace, etc there. -To reset all catched exceptions just restart the server by :Rdebugger command. -You can watch placed catchers in the Breakpoints Window (m by default). -See the bottom line of the window. - -WARNING!!! If you try to set catcher to unexisted exception (e.g., if you -mistyped class of the exception), ruby-debug-ide will be crashed! Then, you -will have to restart the server by :Rdebugger command - -* To stop running server, you can use :RdbStop command: > - :RdbStop - -* For communicating with the rdebug the plugin uses temp file: - ~/.vim/tmp/ruby_debugger. Rdebug writes some response to this file, "kicks" - the plugin remotely calling RubyDebugger.receive_command() by Vim's - client-server functionality and the plugin make actions. For this reason, - you need Vim compiled with +clientserver. - -* The plugin logs all its actions to ~/.vim/tmp/ruby_debugger_log. - -* You also can run Unit tests for the plugin. For this, copy to - ~/.vim/autoload/ ruby_debugger.vim from additionals/autoload (instead of vim/autoload). - It has the same functionality, but with unit tests at end of the file. - To run unit tests, change current directory to some rails project and run > - call g:TU.run() - -* To watch standard output of executing of Ruby script, you can use > - - :RdbLog - -It actually just opens ~/.vim/tmp/ruby_debugger_output, with options: > - setlocal autoread - setlocal wrap - setlocal nonumber - -Also, if plugin AnsiEsc is installed -(http://www.vim.org/scripts/script.php?script_id=302, (it colorizes ANSI escape -sequences, they are used heavily by e.g. ActiveRecord logging)), it will be run - automatically after :RdbLog call to colorize ruby_debugger_output. - - -============================================================================== -DEBUGGING OF TESTS *ruby-debugger-tests* - -The plugin supports debugging of Test::Unit tests, RSpec specs and Cucumber -features by :RdbTest command. Just open file with the test, set some -breakpoints and type: > - :RdbTest - -It equals to running > - :Rdebugger /path/to/some_test.rb " for Test::Unit tests - :Rdebugger '/usr/bin/spec /path/to/some_spec.rb' " for RSpec - :Rdebugger '/usr/bin/cucumber /path/to/some.feature' " for Cucumber feautres - -For debugging Cucumber features, you should set breakpoints in step -definitions file (e.g., user_steps.rb), but start debugger by :RdbTest command -in blabla.feature file. You can't set breakpoints in .feature file (I mean you -can, but they will be ignored), because... well, it is just plain text! :) - -If you store spec or cucumber executables in some different place, not in -/usr/bin (e.g., if you have Windows), you should set path to them explicitly. - -For this, set some variables in your .vimrc. E.g.: > - let g:ruby_debugger_spec_path = 'c:\gembins\spec' " set Rspec path - let g:ruby_debugger_cucumber_path = 'c:\gembins\cucumber' " set Cucumber path - -A single rspec test can be invoked by RdbTestSingle which will invoke rspec -and pass the current line to rspec via "-l" argument to rspec. For Cucumber -and Test::Unit all tests/features are run. - -============================================================================== -RUBY 1.9 AND RAILS 3 *ruby-debugger-ruby19* - -If you want to use vim-ruby-debugger with Ruby 1.9, the best way will be using -'rvm' (http://rvm.beginrescueend.com/). Install it and then install ruby 1.9: -> - rvm install 1.9.2 - -Then, switch to ruby 1.9.2 version: > - - rvm 1.9.2 - -Make sure you use correct version of Ruby: > - - which ruby - -it will show path to current ruby executable, e.g. > - - /Users/anton/.rvm/rubies/ruby-1.9.2-p0/bin/ruby - -Then install ruby-debug-ide19 gem: > - - gem install ruby-debug-ide19 - -After installation of the gem, you need make sure path to rdebug-ide points now -to RVM dir: > - $ which rdebug-ide - /Users/anton/.rvm/gems/ruby-1.9.2-p0/bin/rdebug-ide - -Now you can use vim-ruby-debugger for debugging ruby 1.9 scripts. If you want -to debug Rails 3 applications, you (of course) need to install it: > - - gem install rails - -then create new Rails 3 app somewhere: > - - rails new demo - -go to the dir with the project, and run vim there. Then, run: > - - :Rdebugger 'script/rails server' - -to run Rails 3 app. Then, you can set breakpoints, watch variables, etc, as -usual. - -I really recommend to try it with Ruby 1.9 and Rails 3, the plugin will help -you to learn how Rails 3 works inside - it is a good experience! :) - -============================================================================== -TROUBLESHOOTING *ruby-debugger-issues* - -1. Sometimes (e.g., if you use Mac OS and mvim), you can notice strange and -not correct behavior of the plugin (only a couple commands work, you can't see -variables list, next/step commands don't work). Make sure variable -'g:ruby_debugger_progname' contains proper name of Vim's executable (mvim -if you run mvim, gvim for gvim, vim for vim): > - :echo g:ruby_debugger_progname - -If it contains some incorrect value, set it in your .vimrc. E.g. for mvim: > - let g:ruby_debugger_progname = 'mvim' - -If Vim's executable directory is not in your PATH environment variable, set -full path to executable: > - let g:ruby_debugger_progname = '/opt/local/bin/mvim' - -2. If you try to set exceptions catcher to unexisted exception class, -ruby-debug-ide will be crushed with error. This is issue of the -ruby-debud-ide. - -3. By default, if Vim is compiled with +ruby, the plugin is trying to send -messages to debugger by built-in Ruby interface (details are in ':help ruby'). -Some users have issues with built-in Ruby interface, so they may try to -"degradate" to external Ruby script instead of using built-in Ruby interface. -For that, add to your .vimrc: > - let g:ruby_debugger_builtin_sender = 0 - -and the plugin will call external ruby interpreter instead of built-in -interface. - -4. If you still can't fix the issue, you can enable debug mode by: > - let g:ruby_debugger_debug_mode = 1 -in your .vimrc, and then open the new issue in Github Issue Tracker -(or write email to me) and attach ~/.vim/tmp/ruby_debugger_log file. - -5. Sometimes the default key bindings can conflict with the key bindings of -other plugins. In this case you may want to disable the default bindings of -vim-ruby-debugger and assign your own bindings. For that, use this: > - let g:ruby_debugger_no_maps = 1 -in your .vimrc, and then you can specify your own bindings - -============================================================================== -BUGS *ruby-debugger-bugs* - -If you meet any bug (even small), please, report about it. You can write email -to me (|ruby-debugger-plugin-author|), or even better - write about your issue -here: -> - http://github.com/astashov/vim-ruby-debugger/issues -> -Also, any feedback is highly desired. Please, send all comments, complaints -and compliments to the author. -Thanks! - -============================================================================== -ABOUT *ruby-debugger-about* *ruby-debugger-plugin-author* - -This plugin was written by Anton Astashov. -Email: anton (at) astashov (dot) net -Website: astashov.net - -The latest version of plugin can be found at: - http://github.com/astashov/vim-ruby-debugger - -This plugin is distributable under the same terms as Vim itself. See -|license|. No warranties, expressed or implied. - -============================================================================== -vim:tw=78:ts=8:ft=help:norl: diff --git a/vim/bundle/vim-ruby-debugger/plugin/ruby_debugger.vim b/vim/bundle/vim-ruby-debugger/plugin/ruby_debugger.vim deleted file mode 100644 index 57ebcc3..0000000 --- a/vim/bundle/vim-ruby-debugger/plugin/ruby_debugger.vim +++ /dev/null @@ -1,30 +0,0 @@ -if exists("g:ruby_debugger_loaded") - finish -endif - -if !exists("g:ruby_debugger_no_maps") || !g:ruby_debugger_no_maps - noremap b :call ruby_debugger#load_debugger() call g:RubyDebugger.toggle_breakpoint() - noremap v :call ruby_debugger#load_debugger() call g:RubyDebugger.open_variables() - noremap m :call ruby_debugger#load_debugger() call g:RubyDebugger.open_breakpoints() - noremap t :call ruby_debugger#load_debugger() call g:RubyDebugger.open_frames() - noremap s :call ruby_debugger#load_debugger() call g:RubyDebugger.step() - noremap f :call ruby_debugger#load_debugger() call g:RubyDebugger.finish() - noremap n :call ruby_debugger#load_debugger() call g:RubyDebugger.next() - noremap c :call ruby_debugger#load_debugger() call g:RubyDebugger.continue() - noremap e :call ruby_debugger#load_debugger() call g:RubyDebugger.exit() - noremap d :call ruby_debugger#load_debugger() call g:RubyDebugger.remove_breakpoints() -endif - -command! -nargs=* -complete=file Rdebugger call ruby_debugger#load_debugger() | call g:RubyDebugger.start() -command! -nargs=0 RdbStop call g:RubyDebugger.stop() -command! -nargs=1 RdbCommand call g:RubyDebugger.send_command_wrapper() -command! -nargs=0 RdbTest call g:RubyDebugger.run_test() -command! -nargs=0 RdbTestSingle call g:RubyDebugger.run_test(" -l " . line(".")) -command! -nargs=1 RdbEval call g:RubyDebugger.eval() -command! -nargs=1 RdbCond call g:RubyDebugger.conditional_breakpoint() -command! -nargs=1 RdbCatch call g:RubyDebugger.catch_exception() -command! -nargs=0 RdbLog call ruby_debugger#load_debugger() | call g:RubyDebugger.show_log() - -let g:ruby_debugger_loaded = 1 - - diff --git a/vim/bundle/vim-ruby-debugger/src/additionals/autoload/ruby_debugger.vim b/vim/bundle/vim-ruby-debugger/src/additionals/autoload/ruby_debugger.vim deleted file mode 100644 index 13bc171..0000000 --- a/vim/bundle/vim-ruby-debugger/src/additionals/autoload/ruby_debugger.vim +++ /dev/null @@ -1,2906 +0,0 @@ -" Init section - set default values, highlight colors - -let s:rdebug_port = 39767 -let s:debugger_port = 39768 -" hostname() returns something strange in Windows (E98BD9A419BB41D), so set hostname explicitly -let s:hostname = '127.0.0.1' "hostname() -" ~/.vim for Linux, vimfiles for Windows -let s:runtime_dir = expand(':h:h') -" File for communicating between intermediate Ruby script ruby_debugger.rb and -" this plugin -let s:tmp_file = s:runtime_dir . '/tmp/ruby_debugger' -let s:logger_file = s:runtime_dir . '/tmp/ruby_debugger_log' -let s:server_output_file = s:runtime_dir . '/tmp/ruby_debugger_output' -" Default id for sign of current line -let s:current_line_sign_id = 120 -let s:separator = "++vim-ruby-debugger separator++" -let s:sign_id = 0 - -" Create tmp directory if it doesn't exist -if !isdirectory(s:runtime_dir . '/tmp') - call mkdir(s:runtime_dir . '/tmp') -endif - -" Init breakpoint signs -hi def link Breakpoint Error -sign define breakpoint linehl=Breakpoint text=xx - -" Init current line signs -hi def link CurrentLine DiffAdd -sign define current_line linehl=CurrentLine text=>> - -" Loads this file. Required for autoloading the code for this plugin -fun! ruby_debugger#load_debugger() - if !s:check_prerequisites() - finish - endif -endf - -fun! ruby_debugger#statusline() - let is_running = g:RubyDebugger.is_running() - if is_running == 0 - return '' - endif - return '[ruby debugger running]' -endfunction - -" Check all requirements for the current plugin -fun! s:check_prerequisites() - let problems = [] - if v:version < 700 - call add(problems, "RubyDebugger: This plugin requires Vim >= 7.") - endif - if !has("clientserver") - call add(problems, "RubyDebugger: This plugin requires +clientserver option") - endif - if !executable("rdebug-ide") - call add(problems, "RubyDebugger: You don't have installed 'ruby-debug-ide' gem or executable 'rdebug-ide' can't be found in your PATH") - endif - if !(has("win32") || has("win64")) && !executable("lsof") - call add(problems, "RubyDebugger: You don't have 'lsof' installed or executable 'lsof' can't be found in your PATH") - endif - if g:ruby_debugger_builtin_sender && !has("ruby") - call add(problems, "RubyDebugger: You are trying to use built-in Ruby in Vim, but your Vim doesn't compiled with +ruby. Set g:ruby_debugger_builtin_sender = 0 in your .vimrc to resolve that issue.") - end - if empty(problems) - return 1 - else - for p in problems - echoerr p - endfor - return 0 - endif -endf - - -" End of init section - - -" *** Common (global) functions - -" Split string of tags to List. E.g., -" -" will be splitted to -" [ '', '' ] -function! s:get_tags(cmd) - let tags = [] - let cmd = a:cmd - " Remove wrap tags - let inner_tags_match = s:get_inner_tags(cmd) - if !empty(inner_tags_match) - " Then find every tag and remove it from source string - let pattern = '<.\{-}\/>' - let inner_tags = inner_tags_match[1] - let tagmatch = matchlist(inner_tags, pattern) - while empty(tagmatch) == 0 - call add(tags, tagmatch[0]) - " These symbols are interpretated as special, we need to escape them - let tagmatch[0] = escape(tagmatch[0], '[]~*\') - " Remove it from source string - let inner_tags = substitute(inner_tags, tagmatch[0], '', '') - " Find next tag - let tagmatch = matchlist(inner_tags, pattern) - endwhile - endif - return tags -endfunction - - -" Converts command with relative path to absolute path. If given command -" contains relative path, it will try to use 'which' on it first, and if -" 'which' returns nothing, it will add current dir path to given command -function! s:get_escaped_absolute_path(command) - " Remove leading and trailing quotes - let given_path = a:command - let given_path = substitute(given_path, '"', '\"', "g") - let given_path = substitute(given_path, "^'", '', "g") - let given_path = substitute(given_path, "'$", '', "g") - if given_path[0] == '/' - let absolute_path = given_path - else - let parts = split(given_path) - let relative_command = remove(parts, 0) - let arguments = join(parts) - let absolute_command = "" - " I don't know Windows analogue for 'which', if you know - feel free to add it here - if !(has("win32") || has("win64")) - let absolute_command = s:strip(system('which ' . relative_command)) - endif - if absolute_command[0] != '/' - let absolute_command = getcwd() . '/' . relative_command - endif - let absolute_path = "\"'" . absolute_command . "' " . arguments . '"' - endif - return absolute_path -endfunction - - -" Return a string without leading and trailing spaces and linebreaks. -function! s:strip(input_string) - return substitute(substitute(a:input_string, "\n", '', 'g'), '(\s*\(.\{-}\)\s*', '\1', 'g') -endfunction - - -" Shortcut for g:RubyDebugger.logger.debug -function! s:log(string) - call g:RubyDebugger.logger.put(a:string) -endfunction - - -" Return match of inner tags without wrap tags. E.g.: -" mathes only -function! s:get_inner_tags(cmd) - return matchlist(a:cmd, '^<.\{-}>\(.\{-}\)<\/.\{-}>$') -endfunction - - -" Return Dict of attributes. -" E.g., from it returns -" {'name' : 'a', 'value' : 'b'} -function! s:get_tag_attributes(cmd) - let attributes = {} - let cmd = a:cmd - " Find type of used quotes (" or ') - let quote_match = matchlist(cmd, "\\w\\+=\\(.\\)") - let quote = empty(quote_match) ? "\"" : escape(quote_match[1], "'\"") - let pattern = "\\(\\w\\+\\)=" . quote . "\\(.\\{-}\\)" . quote - " Find every attribute and remove it from source string - let attrmatch = matchlist(cmd, pattern) - while !empty(attrmatch) - " Values of attributes can be escaped by HTML entities, unescape them - let attributes[attrmatch[1]] = s:unescape_html(attrmatch[2]) - " These symbols are interpretated as special, we need to escape them - let attrmatch[0] = escape(attrmatch[0], '[]~*\') - " Remove it from source string - let cmd = substitute(cmd, attrmatch[0], '', '') - " Find next attribute - let attrmatch = matchlist(cmd, pattern) - endwhile - return attributes -endfunction - - -" Unescape HTML entities -function! s:unescape_html(html) - let result = substitute(a:html, "&", "\\&", "g") - let result = substitute(result, """, "\"", "g") - let result = substitute(result, "<", "<", "g") - let result = substitute(result, ">", ">", "g") - return result -endfunction - - -function! s:quotify(exp) - let quoted = a:exp - let quoted = substitute(quoted, "\"", "\\\\\"", 'g') - return quoted -endfunction - - -" Get filename of current buffer -function! s:get_filename() - return expand("%:p") -endfunction - - -" Send message to debugger. This function should never be used explicitly, -" only through g:RubyDebugger.send_command function -function! s:send_message_to_debugger(message) - call s:log("Sending a message to ruby_debugger.rb: '" . a:message . "'") - if g:ruby_debugger_fast_sender - call s:log("Trying to use experimental 'fast_sender'") - let cmd = s:runtime_dir . "/bin/socket " . s:hostname . " " . s:debugger_port . " \"" . a:message . "\"" - call s:log("Executing command: " . cmd) - call system(cmd) - else - if g:ruby_debugger_builtin_sender - call s:log("Using Vim built-in Ruby to send message") -ruby << RUBY - require 'socket' - attempts = 0 - a = nil - host = VIM::evaluate("s:hostname") - port = VIM::evaluate("s:debugger_port") - message = VIM::evaluate("a:message").gsub("\\\"", '"') - begin - a = TCPSocket.open(host, port) - a.puts(message) - a.close - rescue Errno::ECONNREFUSED - attempts += 1 - if attempts < 400 - sleep 0.05 - retry - else - puts("#{host}:#{port} can not be opened") - exit - end - ensure - a.close if a && !a.closed? - end -RUBY - else - let script = "ruby -e \"require 'socket'; " - let script .= "attempts = 0; " - let script .= "a = nil; " - let script .= "begin; " - let script .= "a = TCPSocket.open('" . s:hostname . "', " . s:debugger_port . "); " - let script .= "a.puts(%q[" . substitute(substitute(a:message, '[', '\[', 'g'), ']', '\]', 'g') . "]);" - let script .= "a.close; " - let script .= "rescue Errno::ECONNREFUSED; " - let script .= "attempts += 1; " - let script .= "if attempts < 400; " - let script .= "sleep 0.05; " - let script .= "retry; " - let script .= "else; " - let script .= "puts('" . s:hostname . ":" . s:debugger_port . " can not be opened'); " - let script .= "exit; " - let script .= "end; " - let script .= "ensure; " - let script .= "a.close if a && !a.closed?; " - let script .= "end; \"" - call s:log("Using system-wide Ruby to send message, the command is: " . script) - let output = system(script) - call s:log("Command has returned following output: " . output) - if output =~ 'can not be opened' - call s:log("Can't send a message to rdebug - port is not opened") - endif - endif - endif -endfunction - - -function! s:unplace_sign_of_current_line() - if has("signs") - exe ":sign unplace " . s:current_line_sign_id - endif -endfunction - - -" Remove all variables of current line, remove current line sign. Usually it -" is needed before next/step/cont commands -function! s:clear_current_state() - call s:unplace_sign_of_current_line() - let g:RubyDebugger.variables = {} - let g:RubyDebugger.frames = [] - " Clear variables and frames window (just show our empty variables Dict) - if s:variables_window.is_open() - call s:variables_window.open() - endif - if s:frames_window.is_open() - call s:frames_window.open() - endif -endfunction - - -" Open given file and jump to given line -" (stolen from NERDTree) -function! s:jump_to_file(file, line) - "if the file is already open in this tab then just stick the cursor in it - let window_number = bufwinnr('^' . a:file . '$') - if window_number != -1 - exe window_number . "wincmd w" - else - " Check if last accessed window is usable to use it - " Usable window - not quickfix, explorer, modified, etc - if !s:is_window_usable(winnr("#")) - exe s:first_normal_window() . "wincmd w" - else - " If it is usable, jump to it - exe 'wincmd p' - endif - exe "edit " . a:file - endif - exe "normal " . a:line . "G" -endfunction - - -" Return 1 if window is usable (not quickfix, explorer, modified, only one -" window, ...) -function! s:is_window_usable(winnumber) - "If there is only one window (winnr("$") - windows count) - if winnr("$") ==# 1 - return 0 - endif - - " Current window number - let oldwinnr = winnr() - - " Switch to given window and check it - exe a:winnumber . "wincmd p" - let specialWindow = getbufvar("%", '&buftype') != '' || getwinvar('%', '&previewwindow') - let modified = &modified - - exe oldwinnr . "wincmd p" - - "if it is a special window, e.g. quickfix or another explorer plugin - if specialWindow - return 0 - endif - - if &hidden - return 1 - endif - - " If this window is modified, but there is another opened window with - " current file, return 1. Otherwise - 0 - return !modified || s:buf_in_windows(winbufnr(a:winnumber)) >= 2 -endfunction - - -" Determine the number of windows open to this buffer number. -function! s:buf_in_windows(buffer_number) - let count = 0 - let window_number = 1 - while 1 - let buffer_number = winbufnr(window_number) - if buffer_number < 0 - break - endif - if buffer_number ==# a:buffer_number - let count = count + 1 - endif - let window_number = window_number + 1 - endwhile - - return count -endfunction - - -" Find first 'normal' window (not quickfix, explorer, etc) -function! s:first_normal_window() - let i = 1 - while i <= winnr("$") - let bnum = winbufnr(i) - if bnum != -1 && getbufvar(bnum, '&buftype') ==# '' && !getwinvar(i, '&previewwindow') - return i - endif - let i += 1 - endwhile - return -1 -endfunction - -" *** Queue class (start) - -let s:Queue = {} - -" ** Public methods - -" Constructor of new queue. -function! s:Queue.new() dict - let var = copy(self) - let var.queue = [] - let var.after = "" - return var -endfunction - - -" Execute next command in the queue and remove it from queue -function! s:Queue.execute() dict - if !empty(self.queue) - call s:log("Executing queue") - let message = join(self.queue, s:separator) - call self.empty() - call g:RubyDebugger.send_command(message) - endif -endfunction - - -" Execute 'after' hook only if queue is empty -function! s:Queue.after_hook() dict - if self.after != "" && empty(self.queue) - call self.after() - endif -endfunction - - -function! s:Queue.add(element) dict - call s:log("Adding '" . a:element . "' to queue") - call add(self.queue, a:element) -endfunction - - -function! s:Queue.empty() dict - let self.queue = [] -endfunction - - -" *** Queue class (end) - - - - -" *** Public interface (start) - -let RubyDebugger = { 'commands': {}, 'variables': {}, 'settings': {}, 'breakpoints': [], 'frames': [], 'exceptions': [] } -let g:RubyDebugger.queue = s:Queue.new() - - -" Run debugger server. It takes one optional argument with path to debugged -" ruby script ('script/server webrick' by default) -function! RubyDebugger.start(...) dict - call s:log("Executing :Rdebugger...") - let g:RubyDebugger.server = s:Server.new(s:hostname, s:rdebug_port, s:debugger_port, s:runtime_dir, s:tmp_file, s:server_output_file) - let script_string = a:0 && !empty(a:1) ? a:1 : g:ruby_debugger_default_script - let params = a:0 && a:0 > 1 && !empty(a:2) ? a:2 : [] - echo "Loading debugger..." - call g:RubyDebugger.server.start(s:get_escaped_absolute_path(script_string), params) - - let g:RubyDebugger.exceptions = [] - for breakpoint in g:RubyDebugger.breakpoints - call g:RubyDebugger.queue.add(breakpoint.command()) - endfor - call g:RubyDebugger.queue.add('start') - echo "Debugger started" - call g:RubyDebugger.queue.execute() -endfunction - - -" Stop running server. -function! RubyDebugger.stop() dict - if has_key(g:RubyDebugger, 'server') - call g:RubyDebugger.server.stop() - endif -endfunction - -function! RubyDebugger.is_running() - if has_key(g:RubyDebugger, 'server') - return g:RubyDebugger.server.is_running() - endif - return 0 -endfunction - -" This function receives commands from the debugger. When ruby_debugger.rb -" gets output from rdebug-ide, it writes it to the special file and 'kick' -" the plugin by remotely calling RubyDebugger.receive_command(), e.g.: -" vim --servername VIM --remote-send 'call RubyDebugger.receive_command()' -" That's why +clientserver is required -" This function analyzes the special file and gives handling to right command -function! RubyDebugger.receive_command() dict - let file_contents = join(readfile(s:tmp_file), "") - call s:log("Received command: " . file_contents) - let commands = split(file_contents, s:separator) - for cmd in commands - if !empty(cmd) - if match(cmd, '') != -1 - call g:RubyDebugger.commands.set_variables(cmd) - elseif match(cmd, '') != -1 - call g:RubyDebugger.commands.error(cmd) - elseif match(cmd, '') != -1 - call g:RubyDebugger.commands.message(cmd) - elseif match(cmd, '') != -1 - call g:RubyDebugger.commands.trace(cmd) - endif - endif - endfor - call g:RubyDebugger.queue.after_hook() - call g:RubyDebugger.queue.execute() -endfunction - - -function! RubyDebugger.send_command_wrapper(command) - call g:RubyDebugger.send_command(a:command) -endfunction - -" We set function this way, because we want have possibility to mock it by -" other function in tests -let RubyDebugger.send_command = function("send_message_to_debugger") - - -" Open variables window -function! RubyDebugger.open_variables() dict - call s:variables_window.toggle() - call s:log("Opened variables window") - call g:RubyDebugger.queue.execute() -endfunction - - -" Open breakpoints window -function! RubyDebugger.open_breakpoints() dict - call s:breakpoints_window.toggle() - call s:log("Opened breakpoints window") - call g:RubyDebugger.queue.execute() -endfunction - - -" Open frames window -function! RubyDebugger.open_frames() dict - call s:frames_window.toggle() - call s:log("Opened frames window") - call g:RubyDebugger.queue.execute() -endfunction - - -" Set/remove breakpoint at current position. If argument -" is given, it will set conditional breakpoint (argument is condition) -function! RubyDebugger.toggle_breakpoint(...) dict - let line = line(".") - let file = s:get_filename() - call s:log("Trying to toggle a breakpoint in the file " . file . ":" . line) - let existed_breakpoints = filter(copy(g:RubyDebugger.breakpoints), 'v:val.line == ' . line . ' && v:val.file == "' . escape(file, '\') . '"') - " If breakpoint with current file/line doesn't exist, create it. Otherwise - - " remove it - if empty(existed_breakpoints) - call s:log("There is no already set breakpoint, so create new one") - let breakpoint = s:Breakpoint.new(file, line) - call add(g:RubyDebugger.breakpoints, breakpoint) - call s:log("Added Breakpoint object to RubyDebugger.breakpoints array") - call breakpoint.send_to_debugger() - else - call s:log("There is already set breakpoint presented, so delete it") - let breakpoint = existed_breakpoints[0] - call filter(g:RubyDebugger.breakpoints, 'v:val.id != ' . breakpoint.id) - call s:log("Removed Breakpoint object from RubyDebugger.breakpoints array") - call breakpoint.delete() - endif - " Update info in Breakpoints window - if s:breakpoints_window.is_open() - call s:breakpoints_window.open() - exe "wincmd p" - endif - call g:RubyDebugger.queue.execute() -endfunction - - -" Remove all breakpoints -function! RubyDebugger.remove_breakpoints() dict - for breakpoint in g:RubyDebugger.breakpoints - call breakpoint.delete() - endfor - let g:RubyDebugger.breakpoints = [] - call g:RubyDebugger.queue.execute() -endfunction - - -" Eval the passed in expression -function! RubyDebugger.eval(exp) dict - let quoted = s:quotify(a:exp) - call g:RubyDebugger.queue.add("eval " . quoted) - call g:RubyDebugger.queue.execute() -endfunction - - -" Sets conditional breakpoint where cursor is placed -function! RubyDebugger.conditional_breakpoint(exp) dict - let line = line(".") - let file = s:get_filename() - let existed_breakpoints = filter(copy(g:RubyDebugger.breakpoints), 'v:val.line == ' . line . ' && v:val.file == "' . escape(file, '\') . '"') - " If breakpoint with current file/line doesn't exist, create it. Otherwise - - " remove it - if empty(existed_breakpoints) - echo "You can set condition only to already set breakpoints. Move cursor to set breakpoint and add condition" - else - let breakpoint = existed_breakpoints[0] - let quoted = s:quotify(a:exp) - call breakpoint.add_condition(quoted) - " Update info in Breakpoints window - if s:breakpoints_window.is_open() - call s:breakpoints_window.open() - exe "wincmd p" - endif - call g:RubyDebugger.queue.execute() - endif -endfunction - - -" Catch all exceptions with given name -function! RubyDebugger.catch_exception(exp) dict - if has_key(g:RubyDebugger, 'server') && g:RubyDebugger.server.is_running() - let quoted = s:quotify(a:exp) - let exception = s:Exception.new(quoted) - call add(g:RubyDebugger.exceptions, exception) - if s:breakpoints_window.is_open() - call s:breakpoints_window.open() - exe "wincmd p" - endif - call g:RubyDebugger.queue.execute() - else - echo "Sorry, but you can set Exceptional Breakpoints only with running debugger" - endif -endfunction - - -" Next -function! RubyDebugger.next() dict - call g:RubyDebugger.queue.add("next") - call s:clear_current_state() - call s:log("Step over") - call g:RubyDebugger.queue.execute() -endfunction - - -" Step -function! RubyDebugger.step() dict - call g:RubyDebugger.queue.add("step") - call s:clear_current_state() - call s:log("Step into") - call g:RubyDebugger.queue.execute() -endfunction - - -" Finish -function! RubyDebugger.finish() dict - call g:RubyDebugger.queue.add("finish") - call s:clear_current_state() - call s:log("Step out") - call g:RubyDebugger.queue.execute() -endfunction - - -" Continue -function! RubyDebugger.continue() dict - call g:RubyDebugger.queue.add("cont") - call s:clear_current_state() - call s:log("Continue") - call g:RubyDebugger.queue.execute() -endfunction - - -" Exit -function! RubyDebugger.exit() dict - call g:RubyDebugger.queue.add("exit") - call s:clear_current_state() - call g:RubyDebugger.queue.execute() -endfunction - - -" Show output log of Ruby script -function! RubyDebugger.show_log() dict - exe "view " . s:server_output_file - setlocal autoread - " Per gorkunov's request - setlocal wrap - setlocal nonumber - if exists(":AnsiEsc") - exec ":AnsiEsc" - endif -endfunction - - -" Debug current opened test -function! RubyDebugger.run_test() dict - let file = s:get_filename() - if file =~ '_spec\.rb$' - call g:RubyDebugger.start(g:ruby_debugger_spec_path . ' ' . file) - elseif file =~ '\.feature$' - call g:RubyDebugger.start(g:ruby_debugger_cucumber_path . ' ' . file) - elseif file =~ '_test\.rb$' - call g:RubyDebugger.start(file, ['-Itest']) - endif -endfunction - - -" *** Public interface (end) - - - - -" *** RubyDebugger Commands (what debugger returns) - - -" -" -" Jump to file/line where execution was suspended, set current line sign and get local variables -function! RubyDebugger.commands.jump_to_breakpoint(cmd) dict - let attrs = s:get_tag_attributes(a:cmd) - call s:jump_to_file(attrs.file, attrs.line) - call s:log("Jumped to breakpoint " . attrs.file . ":" . attrs.line) - - if has("signs") - exe ":sign place " . s:current_line_sign_id . " line=" . attrs.line . " name=current_line file=" . attrs.file - endif -endfunction - - -" -" Show message error and jump to given file/line -function! RubyDebugger.commands.handle_exception(cmd) dict - let message_match = matchlist(a:cmd, 'message="\(.\{-}\)"') - call g:RubyDebugger.commands.jump_to_breakpoint(a:cmd) - echo "Exception message: " . s:unescape_html(message_match[1]) -endfunction - - -" -" Confirm setting of exception catcher -function! RubyDebugger.commands.set_exception(cmd) dict - let attrs = s:get_tag_attributes(a:cmd) - call s:log("Exception successfully set: " . attrs.exception) -endfunction - - -" -" Add debugger info to breakpoints (pid of debugger, debugger breakpoint's id) -" Assign rest breakpoints to debugger recursively, if there are breakpoints -" from old server runnings or not assigned breakpoints (e.g., if you at first -" set some breakpoints, and then run the debugger by :Rdebugger) -function! RubyDebugger.commands.set_breakpoint(cmd) - call s:log("Received the breakpoint message, will add PID and number of breakpoint to the Breakpoint object") - let attrs = s:get_tag_attributes(a:cmd) - let file_match = matchlist(attrs.location, '\(.*\):\(.*\)') - let pid = g:RubyDebugger.server.rdebug_pid - - " Find added breakpoint in array and assign debugger's info to it - for breakpoint in g:RubyDebugger.breakpoints - if expand(breakpoint.file) == expand(file_match[1]) && expand(breakpoint.line) == expand(file_match[2]) - call s:log("Found the Breakpoint object for " . breakpoint.file . ":" . breakpoint.line) - let breakpoint.debugger_id = attrs.no - let breakpoint.rdebug_pid = pid - call s:log("Added id: " . breakpoint.debugger_id . ", PID:" . breakpoint.rdebug_pid . " to Breakpoint") - if has_key(breakpoint, 'condition') - call breakpoint.add_condition(breakpoint.condition) - endif - endif - endfor - - call s:log("Breakpoint is set: " . file_match[1] . ":" . file_match[2]) - call g:RubyDebugger.queue.execute() -endfunction - - -" -" -" -" Assign list of got variables to parent variable and (optionally) show them -function! RubyDebugger.commands.set_variables(cmd) - let tags = s:get_tags(a:cmd) - let list_of_variables = [] - - " Create hash from list of tags - for tag in tags - let attrs = s:get_tag_attributes(tag) - let variable = s:Var.new(attrs) - call add(list_of_variables, variable) - endfor - - " If there is no variables, create unnamed root variable. Local variables - " will be chilren of this variable - if g:RubyDebugger.variables == {} - let g:RubyDebugger.variables = s:VarParent.new({'hasChildren': 'true'}) - let g:RubyDebugger.variables.is_open = 1 - let g:RubyDebugger.variables.children = [] - endif - - " If g:RubyDebugger.current_variable exists, then it contains parent - " variable of got subvariables. Assign them to it. - if has_key(g:RubyDebugger, 'current_variable') - let variable = g:RubyDebugger.current_variable - if variable != {} - call variable.add_childs(list_of_variables) - call s:log("Opening child variable: " . variable.attributes.objectId) - " Variables Window is always open if we got subvariables - call s:variables_window.open() - else - call s:log("Can't found variable") - endif - unlet g:RubyDebugger.current_variable - else - " Otherwise, assign them to unnamed root variable - if g:RubyDebugger.variables.children == [] - call g:RubyDebugger.variables.add_childs(list_of_variables) - call s:log("Initializing local variables") - if s:variables_window.is_open() - " show variables only if Variables Window is open - call s:variables_window.open() - endif - endif - endif - -endfunction - - -" -" Just show result of evaluation -function! RubyDebugger.commands.eval(cmd) - " rdebug-ide-gem doesn't escape attributes of tag properly, so we should not - " use usual attribute extractor here... - let match = matchlist(a:cmd, "") - echo "Evaluated expression:\n" . s:unescape_html(match[1]) ."\nResulted value is:\n" . match[2] . "\n" -endfunction - - -" -" Just show exception message -function! RubyDebugger.commands.processing_exception(cmd) - let attrs = s:get_tag_attributes(a:cmd) - let message = "RubyDebugger Exception, type: " . attrs.type . ", message: " . attrs.message - echo message - call s:log(message) -endfunction - - -" -" -" -" -" Assign all frames, fill Frames window by them -function! RubyDebugger.commands.trace(cmd) - let tags = s:get_tags(a:cmd) - let list_of_frames = [] - - " Create hash from list of tags - for tag in tags - let attrs = s:get_tag_attributes(tag) - let frame = s:Frame.new(attrs) - call add(list_of_frames, frame) - endfor - - let g:RubyDebugger.frames = list_of_frames - - if s:frames_window.is_open() - " show backtrace only if Backtrace Window is open - call s:frames_window.open() - endif -endfunction - - -" Error -" Just show error -function! RubyDebugger.commands.error(cmd) - let error_match = s:get_inner_tags(a:cmd) - if !empty(error_match) - let error = error_match[1] - echo "RubyDebugger Error: " . error - call s:log("Got error: " . error) - endif -endfunction - - -" Message -" Just show message -function! RubyDebugger.commands.message(cmd) - let message_match = s:get_inner_tags(a:cmd) - if !empty(message_match) - let message = message_match[1] - echo "RubyDebugger Message: " . message - call s:log("Got message: " . message) - endif -endfunction - - -" *** End of debugger Commands - - - -" *** Window class (start). Abstract Class for creating window. -" Must be inherited. Mostly, stolen from the NERDTree. - -let s:Window = {} -let s:Window['next_buffer_number'] = 1 -let s:Window['position'] = 'botright' -let s:Window['size'] = 10 - -" ** Public methods - -" Constructs new window -function! s:Window.new(name, title) dict - let new_variable = copy(self) - let new_variable.name = a:name - let new_variable.title = a:title - return new_variable -endfunction - - -" Clear all data from window -function! s:Window.clear() dict - silent 1,$delete _ -endfunction - - -" Close window -function! s:Window.close() dict - if !self.is_open() - throw "RubyDebug: Window " . self.name . " is not open" - endif - - if winnr("$") != 1 - call self.focus() - close - exe "wincmd p" - else - " If this is only one window, just quit - :q - endif - call s:log("Closed window with name: " . self.name) -endfunction - - -" Get window number -function! s:Window.get_number() dict - if self._exist_for_tab() - return bufwinnr(self._buf_name()) - else - return -1 - endif -endfunction - - -" Display data to the window -function! s:Window.display() - call s:log("Start displaying data in window with name: " . self.name) - call self.focus() - setlocal modifiable - - let current_line = line(".") - let current_column = col(".") - let top_line = line("w0") - - call self.clear() - - call self._insert_data() - call self._restore_view(top_line, current_line, current_column) - - setlocal nomodifiable - call s:log("Complete displaying data in window with name: " . self.name) -endfunction - - -" Put cursor to the window -function! s:Window.focus() dict - exe self.get_number() . " wincmd w" - call s:log("Set focus to window with name: " . self.name) -endfunction - - -" Return 1 if window is opened -function! s:Window.is_open() dict - return self.get_number() != -1 -endfunction - - -" Open window and display data (stolen from NERDTree) -function! s:Window.open() dict - if !self.is_open() - " create the window - silent exec self.position . ' ' . self.size . ' new' - - if !self._exist_for_tab() - " If the window is not opened/exists, create new - call self._set_buf_name(self._next_buffer_name()) - silent! exec "edit " . self._buf_name() - " This function does not exist in Window class and should be declared in - " descendants - call self.bind_mappings() - else - " Or just jump to opened buffer - silent! exec "buffer " . self._buf_name() - endif - - " set buffer options - setlocal winfixheight - setlocal noswapfile - setlocal buftype=nofile - setlocal nowrap - setlocal foldcolumn=0 - setlocal nobuflisted - setlocal nospell - setlocal nolist - iabc - setlocal cursorline - setfiletype ruby_debugger_window - call s:log("Opened window with name: " . self.name) - endif - - if has("syntax") && exists("g:syntax_on") && !has("syntax_items") - call self.setup_syntax_highlighting() - endif - - call self.display() -endfunction - - -" Open/close window -function! s:Window.toggle() dict - call s:log("Toggling window with name: " . self.name) - if self._exist_for_tab() && self.is_open() - call self.close() - else - call self.open() - end -endfunction - - -" ** Private methods - - -" Return buffer name, that is stored in tab variable -function! s:Window._buf_name() dict - return t:window_{self.name}_buf_name -endfunction - - -" Return 1 if the window exists in current tab -function! s:Window._exist_for_tab() dict - return exists("t:window_" . self.name . "_buf_name") -endfunction - - -" Insert data to the window -function! s:Window._insert_data() dict - let old_p = @p - " Put data to the register and then show it by 'put' command - let @p = self.render() - silent exe "normal \"pP" - let @p = old_p - call s:log("Inserted data to window with name: " . self.name) -endfunction - - -" Calculate correct name for the window -function! s:Window._next_buffer_name() dict - let name = self.name . s:Window.next_buffer_number - let s:Window.next_buffer_number += 1 - return name -endfunction - - -" Restore the view -function! s:Window._restore_view(top_line, current_line, current_column) dict - let old_scrolloff=&scrolloff - let &scrolloff=0 - call cursor(a:top_line, 1) - normal! zt - call cursor(a:current_line, a:current_column) - let &scrolloff = old_scrolloff - call s:log("Restored view of window with name: " . self.name) -endfunction - - -function! s:Window._set_buf_name(name) dict - let t:window_{self.name}_buf_name = a:name -endfunction - - -" *** Window class (end) - - -" *** WindowVariables class (start) - -" Inherits variables window from abstract window class -let s:WindowVariables = copy(s:Window) - -" ** Public methods - -function! s:WindowVariables.bind_mappings() - nnoremap <2-leftmouse> :call window_variables_activate_node() - nnoremap o :call window_variables_activate_node()" -endfunction - - -" Returns string that contains all variables (for Window.display()) -function! s:WindowVariables.render() dict - let variables = self.title . "\n" - let variables .= (g:RubyDebugger.variables == {} ? '' : g:RubyDebugger.variables.render()) - return variables -endfunction - - -" TODO: Is there some way to call s:WindowVariables.activate_node from mapping -" command? -" Expand/collapse variable under cursor -function! s:window_variables_activate_node() - let variable = s:Var.get_selected() - if variable != {} && variable.type == "VarParent" - if variable.is_open - call variable.close() - else - call variable.open() - endif - endif - call g:RubyDebugger.queue.execute() -endfunction - - -" Add syntax highlighting -function! s:WindowVariables.setup_syntax_highlighting() - execute "syn match rdebugTitle #" . self.title . "#" - - syn match rdebugPart #[| `]\+# - syn match rdebugPartFile #[| `]\+-# contains=rdebugPart nextgroup=rdebugChild contained - syn match rdebugChild #.\{-}\t# nextgroup=rdebugType contained - - syn match rdebugClosable #[| `]\+\~# contains=rdebugPart nextgroup=rdebugParent contained - syn match rdebugOpenable #[| `]\++# contains=rdebugPart nextgroup=rdebugParent contained - syn match rdebugParent #.\{-}\t# nextgroup=rdebugType contained - - syn match rdebugType #.\{-}\t# nextgroup=rdebugValue contained - syn match rdebugValue #.*\t#he=e-1 nextgroup=rdebugId contained - syn match rdebugId #.*# contained - - syn match rdebugParentLine '[| `]\+[+\~].*' contains=rdebugClosable,rdebugOpenable transparent - syn match rdebugChildLine '[| `]\+-.*' contains=rdebugPartFile transparent - - hi def link rdebugTitle Identifier - hi def link rdebugClosable Type - hi def link rdebugOpenable Title - hi def link rdebugPart Special - hi def link rdebugPartFile Type - hi def link rdebugChild Normal - hi def link rdebugParent Directory - hi def link rdebugType Type - hi def link rdebugValue Special - hi def link rdebugId Ignore -endfunction - - -" *** WindowVariables class (end) - - - -" *** WindowBreakpoints class (start) - -" Inherits WindowBreakpoints from Window -let s:WindowBreakpoints = copy(s:Window) - -" ** Public methods - -function! s:WindowBreakpoints.bind_mappings() - nnoremap <2-leftmouse> :call window_breakpoints_activate_node() - nnoremap o :call window_breakpoints_activate_node() - nnoremap d :call window_breakpoints_delete_node() -endfunction - - -" Returns string that contains all breakpoints (for Window.display()) -function! s:WindowBreakpoints.render() dict - let breakpoints = "" - let breakpoints .= self.title . "\n" - for breakpoint in g:RubyDebugger.breakpoints - let breakpoints .= breakpoint.render() - endfor - let exceptions = map(copy(g:RubyDebugger.exceptions), 'v:val.render()') - let breakpoints .= "\nException breakpoints: " . join(exceptions, ", ") - return breakpoints -endfunction - - -" TODO: Is there some way to call s:WindowBreakpoints.activate_node from mapping -" command? -" Open breakpoint under cursor -function! s:window_breakpoints_activate_node() - let breakpoint = s:Breakpoint.get_selected() - if breakpoint != {} - call breakpoint.open() - endif -endfunction - - -" Delete breakpoint under cursor -function! s:window_breakpoints_delete_node() - let breakpoint = s:Breakpoint.get_selected() - if breakpoint != {} - call breakpoint.delete() - call filter(g:RubyDebugger.breakpoints, "v:val.id != " . breakpoint.id) - call s:breakpoints_window.open() - endif -endfunction - - -" Add syntax highlighting -function! s:WindowBreakpoints.setup_syntax_highlighting() dict - execute "syn match rdebugTitle #" . self.title . "#" - - syn match rdebugId "^\d\+\s" contained nextgroup=rdebugDebuggerId - syn match rdebugDebuggerId "\d*\s" contained nextgroup=rdebugFile - syn match rdebugFile ".*:" contained nextgroup=rdebugLine - syn match rdebugLine "\d\+" contained - - syn match rdebugWrapper "^\d\+.*" contains=rdebugId transparent - - hi def link rdebugId Directory - hi def link rdebugDebuggerId Type - hi def link rdebugFile Normal - hi def link rdebugLine Special -endfunction - - -" *** WindowBreakpoints class (end) - - - -" *** WindowFrames class (start) - -" Inherits WindowFrames from Window -let s:WindowFrames = copy(s:Window) - -" ** Public methods - -function! s:WindowFrames.bind_mappings() - nnoremap <2-leftmouse> :call window_frames_activate_node() - nnoremap o :call window_frames_activate_node() -endfunction - - -" Returns string that contains all frames (for Window.display()) -function! s:WindowFrames.render() dict - let frames = "" - let frames .= self.title . "\n" - for frame in g:RubyDebugger.frames - let frames .= frame.render() - endfor - return frames -endfunction - - -" Open frame under cursor -function! s:window_frames_activate_node() - let frame = s:Frame.get_selected() - if frame != {} - call frame.open() - endif -endfunction - - -" Add syntax highlighting -function! s:WindowFrames.setup_syntax_highlighting() dict - execute "syn match rdebugTitle #" . self.title . "#" - - syn match rdebugId "^\d\+\s" contained nextgroup=rdebugFile - syn match rdebugFile ".*:" contained nextgroup=rdebugLine - syn match rdebugLine "\d\+" contained - - syn match rdebugWrapper "^\d\+.*" contains=rdebugId transparent - - hi def link rdebugId Directory - hi def link rdebugFile Normal - hi def link rdebugLine Special -endfunction - - -" *** WindowFrames class (end) - - - - -" *** Var proxy class (start) - -let s:Var = { 'id' : 0 } - -" ** Public methods - -" This is a proxy method for creating new variable -function! s:Var.new(attrs) - if has_key(a:attrs, 'hasChildren') && a:attrs['hasChildren'] == 'true' - return s:VarParent.new(a:attrs) - else - return s:VarChild.new(a:attrs) - end -endfunction - - -" Get variable under cursor -function! s:Var.get_selected() - let line = getline(".") - " Get its id - it is last in the string - let match = matchlist(line, '.*\t\(\d\+\)$') - let id = get(match, 1) - if id - let variable = g:RubyDebugger.variables.find_variable({'id' : id}) - return variable - else - return {} - endif -endfunction - - -" *** Var proxy class (end) - - - -" *** VarChild class (start) - -let s:VarChild = {} - -" ** Public methods - -" Constructs new variable without childs -function! s:VarChild.new(attrs) - let new_variable = copy(self) - let new_variable.attributes = a:attrs - let new_variable.parent = {} - let new_variable.level = 0 - let new_variable.type = "VarChild" - let s:Var.id += 1 - let new_variable.id = s:Var.id - return new_variable -endfunction - - -" Renders data of the variable -function! s:VarChild.render() - return self._render(0, 0, [], len(self.parent.children) ==# 1) -endfunction - - -" VarChild can't be opened because it can't have children. But VarParent can -function! s:VarChild.open() - return 0 -endfunction - - -" VarChild can't be closed because it can't have children. But VarParent can -function! s:VarChild.close() - return 0 -endfunction - - -" VarChild can't be parent. But VarParent can. If Var have hasChildren == -" true, then it is parent -function! s:VarChild.is_parent() - return has_key(self.attributes, 'hasChildren') && get(self.attributes, 'hasChildren') ==# 'true' -endfunction - - -" Output format for Variables Window -function! s:VarChild.to_s() - return get(self.attributes, "name", "undefined") . "\t" . get(self.attributes, "type", "undefined") . "\t" . get(self.attributes, "value", "undefined") . "\t" . get(self, "id", "0") -endfunction - - -" Find and return variable by given Dict of attrs, e.g.: {'name' : 'var1'} -function! s:VarChild.find_variable(attrs) - if self._match_attributes(a:attrs) - return self - else - return {} - endif -endfunction - - -" Find and return array of variables that match given Dict of attrs -function! s:VarChild.find_variables(attrs) - let variables = [] - if self._match_attributes(a:attrs) - call add(variables, self) - endif - return variables -endfunction - - -" ** Private methods - - -" Recursive function, that renders Variable and all its childs (if they are -" presented). Stolen from NERDTree -function! s:VarChild._render(depth, draw_text, vertical_map, is_last_child) - let output = "" - if a:draw_text ==# 1 - let tree_parts = '' - - " get all the leading spaces and vertical tree parts for this line - if a:depth > 1 - for j in a:vertical_map[0:-2] - if j ==# 1 - let tree_parts = tree_parts . '| ' - else - let tree_parts = tree_parts . ' ' - endif - endfor - endif - - " get the last vertical tree part for this line which will be different - " if this node is the last child of its parent - if a:is_last_child - let tree_parts = tree_parts . '`' - else - let tree_parts = tree_parts . '|' - endif - - " smack the appropriate dir/file symbol on the line before the file/dir - " name itself - if self.is_parent() - if self.is_open - let tree_parts = tree_parts . '~' - else - let tree_parts = tree_parts . '+' - endif - else - let tree_parts = tree_parts . '-' - endif - let line = tree_parts . self.to_s() - let output = output . line . "\n" - - endif - - if self.is_parent() && self.is_open - if len(self.children) > 0 - - " draw all the nodes children except the last - let last_index = len(self.children) - 1 - if last_index > 0 - for i in self.children[0:last_index - 1] - let output = output . i._render(a:depth + 1, 1, add(copy(a:vertical_map), 1), 0) - endfor - endif - - " draw the last child, indicating that it IS the last - let output = output . self.children[last_index]._render(a:depth + 1, 1, add(copy(a:vertical_map), 0), 1) - - endif - endif - - return output - -endfunction - - -" Return 1 if *all* given attributes (pairs key/value) match to current -" variable -function! s:VarChild._match_attributes(attrs) - let conditions = 1 - for attr in keys(a:attrs) - if has_key(self.attributes, attr) - " If current key is contained in attributes of variable (they were - " attributes in tag, then trying to match there. - let conditions = conditions && self.attributes[attr] == a:attrs[attr] - elseif has_key(self, attr) - " Otherwise, if current key is contained in auxiliary attributes of the - " variable, trying to match there - let conditions = conditions && self[attr] == a:attrs[attr] - else - " Otherwise, this variable is not match - let conditions = 0 - break - endif - endfor - return conditions -endfunction - - -" *** VarChild class (end) - - - - -" *** VarParent class (start) - -" Inherits VarParent from VarChild -let s:VarParent = copy(s:VarChild) - -" ** Public methods - - -" Initializes new variable with childs -function! s:VarParent.new(attrs) - if !has_key(a:attrs, 'hasChildren') || a:attrs['hasChildren'] != 'true' - throw "RubyDebug: VarParent must be initialized with hasChildren = true" - endif - let new_variable = copy(self) - let new_variable.attributes = a:attrs - let new_variable.parent = {} - let new_variable.is_open = 0 - let new_variable.level = 0 - let new_variable.children = [] - let new_variable.type = "VarParent" - let s:Var.id += 1 - let new_variable.id = s:Var.id - return new_variable -endfunction - - -" Open variable, init its children and display them -function! s:VarParent.open() - let self.is_open = 1 - call self._init_children() - return 0 -endfunction - - -" Close variable and display it -function! s:VarParent.close() - let self.is_open = 0 - call s:variables_window.display() - if has_key(g:RubyDebugger, "current_variable") - unlet g:RubyDebugger.current_variable - endif - return 0 -endfunction - - -" Renders data of the variable -function! s:VarParent.render() - return self._render(0, 0, [], len(self.children) ==# 1) -endfunction - - - -" Add childs to the variable. You always should use this method instead of -" explicit assigning to children property (like 'add(self.children, variables)') -function! s:VarParent.add_childs(childs) - " If children are given by array, extend self.children by this array - if type(a:childs) == type([]) - for child in a:childs - let child.parent = self - let child.level = self.level + 1 - endfor - call extend(self.children, a:childs) - else - " Otherwise, add child to self.children - let a:childs.parent = self - let child.level = self.level + 1 - call add(self.children, a:childs) - end -endfunction - - -" Find and return variable by given Dict of attrs, e.g.: {'name' : 'var1'} -" If current variable doesn't match these attributes, try to find in children -function! s:VarParent.find_variable(attrs) - if self._match_attributes(a:attrs) - return self - else - for child in self.children - let result = child.find_variable(a:attrs) - if result != {} - return result - endif - endfor - endif - return {} -endfunction - - -" Find and return array of variables that match given Dict of attrs. -" Try to match current variable and its children -function! s:VarParent.find_variables(attrs) - let variables = [] - if self._match_attributes(a:attrs) - call add(variables, self) - endif - for child in self.children - call extend(variables, child.find_variables(a:attrs)) - endfor - return variables -endfunction - - -" ** Private methods - - -" Update children of the variable -function! s:VarParent._init_children() - " Remove all the current child nodes - let self.children = [] - - " Get children - if has_key(self.attributes, 'objectId') - let g:RubyDebugger.current_variable = self - call g:RubyDebugger.queue.add('var instance ' . self.attributes.objectId) - endif - -endfunction - - -" *** VarParent class (end) - - - -" *** Logger class (start) - -let s:Logger = {} - -function! s:Logger.new(file) - let new_variable = copy(self) - let new_variable.file = a:file - call writefile([], new_variable.file) - return new_variable -endfunction - - -" Log datetime and then message. It logs only if debug mode is enabled -" TODO It outputs a bunch of spaces at the front of the entry - fix that. -function! s:Logger.put(string) dict - if g:ruby_debugger_debug_mode - let string = 'Vim plugin, ' . strftime("%H:%M:%S") . ': ' . a:string - exec 'redir >> ' . g:RubyDebugger.logger.file - silent call s:Logger.silent_echo(s:strip(string)) - exec 'redir END' - endif -endfunction - -function! s:Logger.silent_echo(string) - echo a:string -endfunction - -" *** Logger class (end) -" -" - -" *** Breakpoint class (start) - -let s:Breakpoint = { 'id': 0 } - -" ** Public methods - -" Constructor of new brekpoint. Create new breakpoint and set sign. -function! s:Breakpoint.new(file, line) - let var = copy(self) - let var.file = a:file - let var.line = a:line - let s:Breakpoint.id += 1 - let var.id = s:Breakpoint.id - - call var._set_sign() - call s:log("Set breakpoint to: " . var.file . ":" . var.line) - return var -endfunction - - -" Destroyer of the breakpoint. It just sends commands to debugger and destroys -" sign, but you should manually remove it from breakpoints array -function! s:Breakpoint.delete() dict - call self._unset_sign() - call self._send_delete_to_debugger() -endfunction - - -" Add condition to breakpoint. If server is not running, just store it, it -" will be evaluated after starting the server -function! s:Breakpoint.add_condition(condition) dict - let self.condition = a:condition - if has_key(g:RubyDebugger, 'server') && g:RubyDebugger.server.is_running() && has_key(self, 'debugger_id') - call g:RubyDebugger.queue.add(self.condition_command()) - endif -endfunction - - - -" Send adding breakpoint message to debugger, if it is run -function! s:Breakpoint.send_to_debugger() dict - if has_key(g:RubyDebugger, 'server') && g:RubyDebugger.server.is_running() - call s:log("Server is running, so add command to Queue") - call g:RubyDebugger.queue.add(self.command()) - endif -endfunction - - -" Command for setting breakpoint (e.g.: 'break /path/to/file:23') -function! s:Breakpoint.command() dict - return 'break ' . self.file . ':' . self.line -endfunction - - -" Command for adding condition to breakpoin (e.g.: 'condition 1 x>5') -function! s:Breakpoint.condition_command() dict - return 'condition ' . self.debugger_id . ' ' . self.condition -endfunction - - -" Find and return breakpoint under cursor -function! s:Breakpoint.get_selected() dict - let line = getline(".") - let match = matchlist(line, '^\(\d\+\)') - let id = get(match, 1) - let breakpoints = filter(copy(g:RubyDebugger.breakpoints), "v:val.id == " . id) - if !empty(breakpoints) - return breakpoints[0] - else - return {} - endif -endfunction - - -" Output format for Breakpoints Window -function! s:Breakpoint.render() dict - let output = self.id . " " . (exists("self.debugger_id") ? self.debugger_id : '') . " " . self.file . ":" . self.line - if exists("self.condition") - let output .= " " . self.condition - endif - return output . "\n" -endfunction - - -" Open breakpoint in existed/new window -function! s:Breakpoint.open() dict - call s:jump_to_file(self.file, self.line) -endfunction - - -" ** Private methods - - -function! s:Breakpoint._set_sign() dict - if has("signs") - exe ":sign place " . self.id . " line=" . self.line . " name=breakpoint file=" . self.file - endif -endfunction - - -function! s:Breakpoint._unset_sign() dict - if has("signs") - exe ":sign unplace " . self.id - endif -endfunction - - -" Send deleting breakpoint message to debugger, if it is run -" (e.g.: 'delete 5') -function! s:Breakpoint._send_delete_to_debugger() dict - if has_key(g:RubyDebugger, 'server') && g:RubyDebugger.server.is_running() - let message = 'delete ' . self.debugger_id - call g:RubyDebugger.queue.add(message) - endif -endfunction - - -" *** Breakpoint class (end) - -" *** Exception class (start) -" These are ruby exceptions we catch with 'catch Exception' command -" (:RdbCatch) - -let s:Exception = { } - -" ** Public methods - -" Constructor of new exception. -function! s:Exception.new(name) - let var = copy(self) - let var.name = a:name - call s:log("Trying to set exception: " . var.name) - call g:RubyDebugger.queue.add(var.command()) - return var -endfunction - - -" Command for setting exception (e.g.: 'catch NameError') -function! s:Exception.command() dict - return 'catch ' . self.name -endfunction - - -" Output format for Breakpoints Window -function! s:Exception.render() dict - return self.name -endfunction - -" *** Exception class (end) - - - - -" *** Frame class (start) - -let s:Frame = { } - -" ** Public methods - -" Constructor of new frame. -" Create new frame and set sign to it. -function! s:Frame.new(attrs) - let var = copy(self) - let var.no = a:attrs.no - let var.file = a:attrs.file - let var.line = a:attrs.line - if has_key(a:attrs, 'current') - let var.current = (a:attrs.current == 'true') - else - let var.current = 0 - endif - "let s:sign_id += 1 - "let var.sign_id = s:sign_id - "call var._set_sign() - return var -endfunction - - -" Find and return frame under cursor -function! s:Frame.get_selected() dict - let line = getline(".") - let match = matchlist(line, '^\(\d\+\)') - let no = get(match, 1) - let frames = filter(copy(g:RubyDebugger.frames), "v:val.no == " . no) - if !empty(frames) - return frames[0] - else - return {} - endif -endfunction - - -" Output format for Frame Window -function! s:Frame.render() dict - return self.no . (self.current ? ' Current' : ''). " " . self.file . ":" . self.line . "\n" -endfunction - - -" Open frame in existed/new window -function! s:Frame.open() dict - call s:jump_to_file(self.file, self.line) -endfunction - - -" ** Private methods - -function! s:Frame._set_sign() dict - if has("signs") - exe ":sign place " . self.sign_id . " line=" . self.line . " name=frame file=" . self.file - endif -endfunction - - -function! s:Frame._unset_sign() dict - if has("signs") - exe ":sign unplace " . self.sign_id - endif -endfunction - - -" *** Frame class (end) - - - -" *** Server class (start) - -let s:Server = {} - -" ** Public methods - -" Constructor of new server. Just inits it, not runs -function! s:Server.new(hostname, rdebug_port, debugger_port, runtime_dir, tmp_file, output_file) dict - let var = copy(self) - let var.hostname = a:hostname - let var.rdebug_port = a:rdebug_port - let var.debugger_port = a:debugger_port - let var.runtime_dir = a:runtime_dir - let var.tmp_file = a:tmp_file - let var.output_file = a:output_file - call s:log("Initializing Server object, with variables: hostname: " . var.hostname . ", rdebug_port: " . var.rdebug_port . ", debugger_port: " . var.debugger_port . ", runtime_dir: " . var.runtime_dir . ", tmp_file: " . var.tmp_file . ", output_file: " . var.output_file) - return var -endfunction - - -" Start the server. It will kill any listeners on given ports before. -function! s:Server.start(script, params) dict - call s:log("Starting Server, command: " . a:script) - call s:log("Trying to kill all old servers first") - call self._stop_server(self.rdebug_port) - call self._stop_server(self.debugger_port) - call s:log("Servers are killed, trying to start new servers") - " Remove leading and trailing quotes - let script_name = substitute(a:script, "\\(^['\"]\\|['\"]$\\)", '', 'g') - let rdebug = 'rdebug-ide ' . join(a:params, ' ') . ' -p ' . self.rdebug_port . ' -- ' . script_name - let os = has("win32") || has("win64") ? 'win' : 'posix' - " Example - ruby ~/.vim/bin/ruby_debugger.rb 39767 39768 vim VIM /home/anton/.vim/tmp/ruby_debugger posix - let debugger_parameters = ' ' . self.hostname . ' ' . self.rdebug_port . ' ' . self.debugger_port - let debugger_parameters .= ' ' . g:ruby_debugger_progname . ' ' . v:servername . ' "' . self.tmp_file - let debugger_parameters .= '" ' . os . ' ' . g:ruby_debugger_debug_mode . ' ' . s:logger_file - - " Start in background - if has("win32") || has("win64") - silent exe '! start ' . rdebug - let debugger = 'ruby "' . expand(self.runtime_dir . "/bin/ruby_debugger.rb") . '"' . debugger_parameters - silent exe '! start ' . debugger - else - let cmd = rdebug . ' > ' . self.output_file . ' 2>&1 &' - call s:log("Executing command: ". cmd) - call system(cmd) - let debugger_cmd = 'ruby ' . expand(self.runtime_dir . "/bin/ruby_debugger.rb") . debugger_parameters . ' &' - call s:log("Executing command: ". debugger_cmd) - call system(debugger_cmd) - endif - - " Set PIDs of processes - call s:log("Now we need to store PIDs of servers, retrieving them: ") - let self.rdebug_pid = self._get_pid(self.rdebug_port, 1) - let self.debugger_pid = self._get_pid(self.debugger_port, 1) - call s:log("Server PIDs are: rdebug-ide: " . self.rdebug_pid . ", ruby_debugger.rb: " . self.debugger_pid) - - call s:log("Debugger is successfully started") -endfunction - - -" Kill servers and empty PIDs -function! s:Server.stop() dict - call self._kill_process(self.rdebug_pid) - call self._kill_process(self.debugger_pid) - let self.rdebug_pid = "" - let self.debugger_pid = "" -endfunction - - -" Return 1 if processes with set PID exist. -function! s:Server.is_running() dict - return (self._get_pid(self.rdebug_port, 0) =~ '^\d\+$') && (self._get_pid(self.debugger_port, 0) =~ '^\d\+$') -endfunction - - -" ** Private methods - - -" Get PID of process, that listens given port on given host. If must_get_pid -" parameter is true, it will try to get PID for 10 seconds. -function! s:Server._get_pid(port, must_get_pid) - call s:log("Trying to find PID of process on " . a:port . " port, must_get_pid = " . a:must_get_pid) - let attempt = 0 - let pid = self._get_pid_attempt(a:port) - while a:must_get_pid && pid == "" && attempt < 1000 - sleep 10m - let attempt += 1 - let pid = self._get_pid_attempt(a:port) - endwhile - call s:log("PID - " . pid . ", found by " . attempt . " repeats") - return pid -endfunction - - -" Just try to get PID of process and return empty string if it was -" unsuccessful -function! s:Server._get_pid_attempt(port) - call s:log("Trying to find listener of port " . a:port) - if has("win32") || has("win64") - let netstat = system("netstat -anop tcp") - let pid_match = matchlist(netstat, ':' . a:port . '\s.\{-}LISTENING\s\+\(\d\+\)') - let pid = len(pid_match) > 0 ? pid_match[1] : "" - elseif executable('lsof') - let cmd = "lsof -i tcp:" . a:port . " | grep LISTEN | awk '{print $2}'" - call s:log("Executing command: " . cmd) - let pid = system(cmd) - let pid = substitute(pid, '\n', '', '') - else - let pid = "" - endif - call s:log("Found pid - " . pid) - return pid -endfunction - - -" Kill listener of given host/port -function! s:Server._stop_server(port) dict - let pid = self._get_pid(a:port, 0) - if pid =~ '^\d\+$' - call self._kill_process(pid) - endif -endfunction - - -" Kill process with given PID -function! s:Server._kill_process(pid) dict - let message = "Killing server with pid " . a:pid - call s:log(message) - echo message - let cmd = "ruby -e 'Process.kill(9," . a:pid . ")'" - call s:log("Executing command: " . cmd) - call system(cmd) - call s:log("Sleeping 100m...") - sleep 100m - call s:log("Killed server with pid: " . a:pid) -endfunction - - -" *** Server class (end) - - - -" *** Creating instances (start) - -if !exists("g:ruby_debugger_fast_sender") - let g:ruby_debugger_fast_sender = 0 -endif -if !exists("g:ruby_debugger_debug_mode") - let g:ruby_debugger_debug_mode = 0 -endif -" This variable allows to use built-in Ruby (see ':help ruby' and s:send_message_to_debugger function) -if !exists("g:ruby_debugger_builtin_sender") - if has("ruby") - let g:ruby_debugger_builtin_sender = 1 - else - let g:ruby_debugger_builtin_sender = 0 - endif -endif -if !exists("g:ruby_debugger_spec_path") - let g:ruby_debugger_spec_path = '/usr/bin/spec' -endif -if !exists("g:ruby_debugger_cucumber_path") - let g:ruby_debugger_cucumber_path = '/usr/bin/cucumber' -endif -if !exists("g:ruby_debugger_progname") - let g:ruby_debugger_progname = v:progname -endif -if !exists("g:ruby_debugger_default_script") - let g:ruby_debugger_default_script = 'script/server webrick' -endif -if !exists("g:ruby_debugger_no_maps") - let g:ruby_debugger_no_maps = 0 -endif - -" Creating windows -let s:variables_window = s:WindowVariables.new("variables", "Variables_Window") -let s:breakpoints_window = s:WindowBreakpoints.new("breakpoints", "Breakpoints_Window") -let s:frames_window = s:WindowFrames.new("frames", "Backtrace_Window") - -" Init logger. The plugin logs all its actions. If you have some troubles, -" this file can help -let RubyDebugger.logger = s:Logger.new(s:logger_file) -let s:variables_window.logger = RubyDebugger.logger -let s:breakpoints_window.logger = RubyDebugger.logger -let s:frames_window.logger = RubyDebugger.logger - -" *** Creating instances (end) - -let TU = { 'output': '', 'errors': '', 'success': ''} - - -function! TU.run(...) - call g:TU.init() - for key in keys(s:Tests) - " Run tests only if function was called without arguments, of argument == - " current tests group. - if !a:0 || a:1 == key - let g:TU.output = g:TU.output . "\n" . key . ":\n" - if has_key(s:Tests[key], 'before_all') - call s:Tests[key].before_all() - endif - for test in keys(s:Tests[key]) - if test =~ '^test_' - if has_key(s:Tests[key], 'before') - call s:Tests[key].before() - endif - call s:Tests[key][test](test) - if has_key(s:Tests[key], 'after') - call s:Tests[key].after() - endif - endif - endfor - if has_key(s:Tests[key], 'after_all') - call s:Tests[key].after_all() - endif - let g:TU.output = g:TU.output . "\n" - endif - endfor - - call g:TU.show_output() - call g:TU.restore() -endfunction - - -function! TU.init() - let g:TU.breakpoint_id = s:Breakpoint.id - let s:Breakpoint.id = 0 - - let g:TU.variables = g:RubyDebugger.variables - let g:RubyDebugger.variables = {} - - let g:TU.breakpoints = g:RubyDebugger.breakpoints - let g:RubyDebugger.breakpoints = [] - - let g:TU.var_id = s:Var.id - let s:Var.id = 0 - - let s:Mock.breakpoints = 0 - let s:Mock.evals = 0 - - if s:variables_window.is_open() - call s:variables_window.close() - endif - if s:breakpoints_window.is_open() - call s:breakpoints_window.close() - endif - - let g:TU.output = "" - let g:TU.success = "" - let g:TU.errors = "" - - " For correct closing and deleting test files - let g:TU.hidden = &hidden - set nohidden -endfunction - - -function! TU.restore() - let s:Breakpoint.id = g:TU.breakpoint_id - unlet g:TU.breakpoint_id - - let g:RubyDebugger.variables = g:TU.variables - unlet g:TU.variables - - let g:RubyDebugger.breakpoints = g:TU.breakpoints - unlet g:TU.breakpoints - - let s:Var.id = g:TU.var_id - unlet g:TU.var_id - - let &hidden = g:TU.hidden -endfunction - - -function! TU.show_output() - echo g:TU.output . "\n" . g:TU.errors -endfunction - - -function! TU.ok(condition, description, test) - if a:condition - let g:TU.output = g:TU.output . "." - let g:TU.success = g:TU.success . a:test . ": " . a:description . ", true\n" - else - let g:TU.output = g:TU.output . "F" - let g:TU.errors = g:TU.errors . a:test . ": " . a:description . ", expected true, got false.\n" - endif -endfunction - - -function! TU.equal(expected, actual, description, test) - if a:expected == a:actual - let g:TU.output = g:TU.output . "." - let g:TU.success = g:TU.success . a:test . ": " . a:description . ", equals\n" - else - let g:TU.output = g:TU.output . "F" - let g:TU.errors = g:TU.errors . a:test . ": " . a:description . ", expected " . a:expected . ", got " . a:actual . ".\n" - endif -endfunction - - -function! TU.match(expected, actual, description, test) - if a:expected =~ a:actual - let g:TU.output = g:TU.output . "." - let g:TU.success = g:TU.success . a:test . ": " . a:description . ", match one to other\n" - else - let g:TU.output = g:TU.output . "F" - let g:TU.errors = g:TU.errors . a:test . ": " . a:description . ", expected to match " . a:expected . ", got " . a:actual . ".\n" - endif -endfunction - - -let s:Tests = {} - -let s:Mock = { 'breakpoints': 0, 'evals': 0 } - -function! s:mock_debugger(messages, ...) - let commands = [] - let messages_array = split(a:messages, s:separator) - for message in messages_array - let cmd = "" - if message =~ 'break' - let matches = matchlist(message, 'break \(.*\):\(.*\)') - let cmd = '' - let s:Mock.breakpoints += 1 - elseif message =~ 'delete' - let matches = matchlist(message, 'delete \(.*\)') - let cmd = '' - let s:Mock.breakpoints -= 1 - elseif message =~ 'var local' - let cmd = '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - elseif message =~ 'var instance -0x2418a904' - let cmd = '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - elseif message =~ 'var instance -0x2418a907' - let cmd = '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - elseif message =~ 'var instance -0x2418a906' - let cmd = '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - elseif message =~ 'var instance -0x2418a914' - let cmd = '' - let cmd = cmd . "" - let cmd = cmd . '' - elseif message =~ 'var instance -0x2418a916' - let cmd = '' - let cmd = cmd . "" - let cmd = cmd . '' - elseif message =~ 'where' - let filename = s:Mock.file - let cmd = '' - let cmd = cmd . "" - let cmd = cmd . "" - let cmd = cmd . '' - elseif message =~ '^p ' - let p = matchlist(message, "^p \\(.*\\)")[1] - let s:Mock.evals += 1 - let cmd = '' - endif - if cmd != "" - call add(commands, cmd) - endif - endfor - if !empty(commands) - call writefile([ join(commands, s:separator) ], s:tmp_file) - call g:RubyDebugger.receive_command() - endif -endfunction - - -function! s:Mock.mock_debugger() - let g:RubyDebugger.send_command = function("s:mock_debugger") -endfunction - - -function! s:Mock.unmock_debugger() - let g:RubyDebugger.send_command = function("s:send_message_to_debugger") -endfunction - - -function! s:Mock.mock_file() - let filename = s:runtime_dir . "/tmp/ruby_debugger_test_file" - exe "new " . filename - exe "write" - return filename -endfunction - - -function! s:Mock.unmock_file(filename) - silent exe "close" - call delete(a:filename) -endfunction - - - - -let s:Tests.server = {} - -function! s:Tests.server.before_all() - let g:RubyDebugger.breakpoints = [] - let g:RubyDebugger.frames = [] - let g:RubyDebugger.variables = {} -endfunction - -function! s:Tests.server.before() - call g:RubyDebugger.queue.empty() - call s:Server._stop_server(s:rdebug_port) - call s:Server._stop_server(s:debugger_port) -endfunction - -function! s:Tests.server.test_should_run_server(test) - exe "Rdebugger" - call g:TU.ok(type(g:RubyDebugger.server) == type({}), "Server should be initialized", a:test) - call g:TU.ok(g:RubyDebugger.server.is_running(), "Server should be run", a:test) - call g:TU.ok(g:RubyDebugger.server.rdebug_pid != "", "Process rdebug-ide should be run", a:test) - call g:TU.ok(g:RubyDebugger.server.debugger_pid != "", "Process debugger.rb should be run", a:test) -endfunction - - -function! s:Tests.server.test_should_stop_server(test) - exe "Rdebugger" - call g:RubyDebugger.server.stop() - call g:TU.ok(!g:RubyDebugger.server.is_running(), "Server should not be run", a:test) - call g:TU.equal("", s:Server._get_pid(s:rdebug_port, 0), "Process rdebug-ide should not exist", a:test) - call g:TU.equal("", s:Server._get_pid(s:debugger_port, 0), "Process debugger.rb should not exist", a:test) - call g:TU.equal("", g:RubyDebugger.server.rdebug_pid, "Pid of rdebug-ide should be nullified", a:test) - call g:TU.equal("", g:RubyDebugger.server.debugger_pid, "Pid of debugger.rb should be nullified", a:test) -endfunction - - -function! s:Tests.server.test_should_kill_old_server_before_starting_new(test) - exe "Rdebugger" - let old_rdebug_pid = g:RubyDebugger.server.rdebug_pid - let old_debugger_pid = g:RubyDebugger.server.debugger_pid - exe "Rdebugger" - call g:TU.ok(g:RubyDebugger.server.is_running(), "Server should be run", a:test) - call g:TU.ok(g:RubyDebugger.server.rdebug_pid != "", "Process rdebug-ide should be run", a:test) - call g:TU.ok(g:RubyDebugger.server.debugger_pid != "", "Process debugger.rb should be run", a:test) - call g:TU.ok(g:RubyDebugger.server.rdebug_pid != old_rdebug_pid, "Rdebug-ide should have new pid", a:test) - call g:TU.ok(g:RubyDebugger.server.debugger_pid != old_debugger_pid, "Debugger.rb should have new pid", a:test) -endfunction - - - - -let s:Tests.breakpoint = {} - -function! s:Tests.breakpoint.before_all() - call s:Mock.mock_debugger() -endfunction - - -function! s:Tests.breakpoint.after_all() - call s:Mock.unmock_debugger() -endfunction - - -function! s:Tests.breakpoint.before() - let s:Breakpoint.id = 0 - let g:RubyDebugger.frames = [] - let g:RubyDebugger.exceptions = [] - let g:RubyDebugger.breakpoints = [] - let g:RubyDebugger.variables = {} - call g:RubyDebugger.queue.empty() - call s:Server._stop_server(s:rdebug_port) - call s:Server._stop_server(s:debugger_port) - silent exe "only" -endfunction - - -function! s:Tests.breakpoint.test_should_set_breakpoint(test) - exe "Rdebugger" - let filename = s:Mock.mock_file() - let file_pattern = substitute(filename, '[\/\\]', '[\\\/\\\\]', "g") - - call g:RubyDebugger.toggle_breakpoint() - let breakpoint = get(g:RubyDebugger.breakpoints, 0) - call g:TU.equal(1, breakpoint.id, "Id of first breakpoint should == 1", a:test) - call g:TU.match(breakpoint.file, file_pattern, "File should be set right", a:test) - call g:TU.equal(1, breakpoint.line, "Line should be set right", a:test) - " TODO: Find way to test sign - call g:TU.equal(g:RubyDebugger.server.rdebug_pid, breakpoint.rdebug_pid, "Breakpoint should be assigned to running server", a:test) - call g:TU.equal(1, breakpoint.debugger_id, "Breakpoint should get number from debugger", a:test) - call s:Mock.unmock_file(filename) -endfunction - - -function! s:Tests.breakpoint.test_should_add_all_unassigned_breakpoints_to_running_server(test) - let filename = s:Mock.mock_file() - " Write 3 lines of text and set 3 breakpoints (on every line) - exe "normal iblablabla" - exe "normal oblabla" - exe "normal obla" - exe "normal gg" - exe "write" - call g:RubyDebugger.toggle_breakpoint() - exe "normal j" - call g:RubyDebugger.toggle_breakpoint() - exe "normal j" - call g:RubyDebugger.toggle_breakpoint() - - " Lets suggest that some breakpoint was assigned to old server - let g:RubyDebugger.breakpoints[1].rdebug_pid = 'bla' - - call g:TU.equal(3, len(g:RubyDebugger.breakpoints), "3 breakpoints should be set", a:test) - exe "Rdebugger" - call g:TU.equal(3, s:Mock.breakpoints, "3 breakpoints should be assigned", a:test) - for breakpoint in g:RubyDebugger.breakpoints - call g:TU.equal(g:RubyDebugger.server.rdebug_pid, breakpoint.rdebug_pid, "Breakpoint should have PID of running server", a:test) - endfor - call s:Mock.unmock_file(filename) -endfunction - - -function! s:Tests.breakpoint.test_should_remove_all_breakpoints(test) - let filename = s:Mock.mock_file() - " Write 3 lines of text and set 3 breakpoints (on every line) - exe "normal iblablabla" - exe "normal oblabla" - exe "normal obla" - exe "normal gg" - exe "write" - call g:RubyDebugger.toggle_breakpoint() - exe "normal j" - call g:RubyDebugger.toggle_breakpoint() - exe "normal j" - call g:RubyDebugger.toggle_breakpoint() - call g:TU.equal(3, len(g:RubyDebugger.breakpoints), "3 breakpoints should be set", a:test) - - call g:RubyDebugger.remove_breakpoints() - - call g:TU.equal(0, len(g:RubyDebugger.breakpoints), "Breakpoints should be removed", a:test) - - call s:Mock.unmock_file(filename) -endfunction - - -function! s:Tests.breakpoint.test_jump_to_breakpoint_by_breakpoint(test) - call s:Tests.breakpoint.jump_to_breakpoint('breakpoint', a:test) -endfunction - - -function! s:Tests.breakpoint.test_jump_to_breakpoint_by_suspended(test) - call s:Tests.breakpoint.jump_to_breakpoint('suspended', a:test) -endfunction - - -function! s:Tests.breakpoint.test_delete_breakpoint(test) - exe "Rdebugger" - let filename = s:Mock.mock_file() - call g:RubyDebugger.toggle_breakpoint() - call g:RubyDebugger.toggle_breakpoint() - - call g:TU.ok(empty(g:RubyDebugger.breakpoints), "Breakpoint should be removed", a:test) - call g:TU.equal(0, s:Mock.breakpoints, "0 breakpoints should be assigned", a:test) - - call s:Mock.unmock_file(filename) -endfunction - - -function! s:Tests.breakpoint.jump_to_breakpoint(cmd, test) - let filename = s:Mock.mock_file() - let file_pattern = substitute(filename, '[\/\\]', '[\\\/\\\\]', "g") - - " Write 2 lines and set current line to second line. We will jump to first - " line - exe "normal iblablabla" - exe "normal oblabla" - exe "write" - - call g:TU.equal(2, line("."), "Current line before jumping is second", a:test) - - let cmd = '<' . a:cmd . ' file="' . filename . '" line="1" />' - call writefile([ cmd ], s:tmp_file) - call g:RubyDebugger.receive_command() - - call g:TU.equal(1, line("."), "Current line before jumping is first", a:test) - call g:TU.match(expand("%"), file_pattern, "Jumped to correct file", a:test) - - call s:Mock.unmock_file(filename) -endfunction - - -function! s:Tests.breakpoint.test_should_open_window_without_got_breakpoints(test) - call g:RubyDebugger.open_breakpoints() - - call g:TU.ok(s:breakpoints_window.is_open(), "Breakpoints window should opened", a:test) - call g:TU.equal(bufwinnr("%"), s:breakpoints_window.get_number(), "Focus should be into the breakpoints window", a:test) - call g:TU.equal(getline(1), s:breakpoints_window.title, "First line should be name", a:test) - - exe 'close' -endfunction - - -function! s:Tests.breakpoint.test_should_open_window_and_show_breakpoints(test) - let filename = s:Mock.mock_file() - " Replace all windows separators (\) and POSIX separators (/) to [\/] for - " making it cross-platform - let file_pattern = substitute(filename, '[\/\\]', '[\\\/\\\\]', "g") - " Write 2 lines of text and set 2 breakpoints (on every line) - exe "normal iblablabla" - exe "normal oblabla" - exe "normal gg" - exe "write" - call g:RubyDebugger.toggle_breakpoint() - exe "normal j" - call g:RubyDebugger.toggle_breakpoint() - - call s:Mock.unmock_file(filename) - - " Lets suggest that some breakpoint is assigned - let g:RubyDebugger.breakpoints[1].debugger_id = 4 - - call g:RubyDebugger.open_breakpoints() - call g:TU.match(getline(2), '1 ' . file_pattern . ':1', "Should show first breakpoint", a:test) - call g:TU.match(getline(3), '2 4 ' . file_pattern . ':2', "Should show second breakpoint", a:test) - - exe 'close' -endfunction - - -function! s:Tests.breakpoint.test_should_open_selected_breakpoint_from_breakpoints_window(test) - let filename = s:Mock.mock_file() - let file_pattern = substitute(filename, '[\/\\]', '[\\\/\\\\]', "g") - exe "normal iblablabla" - exe "normal oblabla" - call g:RubyDebugger.toggle_breakpoint() - exe "normal gg" - exe "write" - exe "wincmd w" - exe "new" - - call g:TU.ok(expand("%") != filename, "It should not be within the file with breakpoint", a:test) - call g:RubyDebugger.open_breakpoints() - exe 'normal 2G' - call s:window_breakpoints_activate_node() - call g:TU.match(expand("%"), file_pattern, "It should open file with breakpoint", a:test) - call g:TU.equal(2, line("."), "It should jump to line with breakpoint", a:test) - call g:RubyDebugger.open_breakpoints() - - call s:Mock.unmock_file(filename) -endfunction - - -function! s:Tests.breakpoint.test_should_delete_breakpoint_from_breakpoints_window(test) - let filename = s:Mock.mock_file() - call g:RubyDebugger.toggle_breakpoint() - call s:Mock.unmock_file(filename) - call g:TU.ok(!empty(g:RubyDebugger.breakpoints), "Breakpoint should be set", a:test) - - call g:RubyDebugger.open_breakpoints() - exe 'normal 2G' - call s:window_breakpoints_delete_node() - call g:TU.equal('', getline(2), "Breakpoint should not be shown", a:test) - call g:TU.ok(empty(g:RubyDebugger.breakpoints), "Breakpoint should be destroyed", a:test) - - exe 'close' -endfunction - - - -let s:Tests.exceptions = {} - -function! s:Tests.exceptions.before_all() - call s:Mock.mock_debugger() -endfunction - - -function! s:Tests.exceptions.after_all() - call s:Mock.unmock_debugger() -endfunction - - -function! s:Tests.exceptions.before() - let s:Breakpoint.id = 0 - let g:RubyDebugger.frames = [] - let g:RubyDebugger.exceptions = [] - let g:RubyDebugger.variables = {} - call g:RubyDebugger.queue.empty() - call s:Server._stop_server(s:rdebug_port) - call s:Server._stop_server(s:debugger_port) -endfunction - - -function! s:Tests.exceptions.test_should_not_set_exception_catcher_if_debugger_is_not_running(test) - call g:RubyDebugger.catch_exception("NameError") - call g:TU.equal(0, len(g:RubyDebugger.exceptions), "Exception catcher should not be set", a:test) -endfunction - - -function! s:Tests.exceptions.test_should_clear_exceptions_after_restarting_debugger(test) - exe "Rdebugger" - call g:RubyDebugger.catch_exception("NameError") - call g:TU.equal(1, len(g:RubyDebugger.exceptions), "Exception should be set after starting the server", a:test) - exe "Rdebugger" - call g:TU.equal(0, len(g:RubyDebugger.exceptions), "Exception should be cleared after restarting the server", a:test) -endfunction - - -function! s:Tests.exceptions.test_should_display_exceptions_in_window_breakpoints(test) - exe "Rdebugger" - call g:RubyDebugger.catch_exception("NameError") - call g:RubyDebugger.catch_exception("ArgumentError") - call g:RubyDebugger.open_breakpoints() - call g:TU.match('Exception breakpoints: NameError, ArgumentError', getline(3), "Should show exception breakpoints", a:test) - exe 'close' -endfunction - - - - -let s:Tests.frames = {} - -function! s:Tests.frames.before_all() - call s:Mock.mock_debugger() -endfunction - - -function! s:Tests.frames.after_all() - call s:Mock.unmock_debugger() -endfunction - - -function! s:Tests.frames.before() - let s:Breakpoint.id = 0 - let g:RubyDebugger.frames = [] - let g:RubyDebugger.variables = {} - call g:RubyDebugger.queue.empty() - call s:Server._stop_server(s:rdebug_port) - call s:Server._stop_server(s:debugger_port) -endfunction - - -function! s:Tests.frames.test_should_display_frames_in_window_frames(test) - let filename = s:Mock.mock_file() - " Replace all windows separators (\) and POSIX separators (/) to [\/] for - " making it cross-platform - let file_pattern = substitute(filename, '[\/\\]', '[\\\/\\\\]', "g") - let s:Mock.file = filename - call g:RubyDebugger.send_command('where') - - call g:RubyDebugger.open_frames() - call g:TU.match(getline(2), '1 Current ' . file_pattern . ':2', "Should show first frame", a:test) - call g:TU.match(getline(3), '2 ' . file_pattern . ':3', "Should show second frame", a:test) - - exe 'close' -endfunction - - -function! s:Tests.frames.test_should_open_file_with_frame(test) - let filename = s:Mock.mock_file() - let file_pattern = substitute(filename, '[\/\\]', '[\\\/\\\\]', "g") - let s:Mock.file = filename - " Write 3 lines of text and set 3 frames (on every line) - exe "normal iblablabla" - exe "normal oblabla" - exe "normal obla" - exe "normal gg" - exe "write" - exe "wincmd w" - call g:TU.ok(expand("%") != filename, "It should not be within the file with frame", a:test) - - call g:RubyDebugger.send_command('where') - call g:TU.equal(2, len(g:RubyDebugger.frames), "2 frames should be set", a:test) - - call g:RubyDebugger.open_frames() - exe 'normal 3G' - call s:window_frames_activate_node() - call g:TU.match(expand("%"), file_pattern, "It should open file with frame", a:test) - call g:TU.equal(3, line("."), "It should jump to line with frame", a:test) - call g:RubyDebugger.open_frames() - - call s:Mock.unmock_file(filename) -endfunction - - -function! s:Tests.frames.test_should_clear_frames_after_movement_command(test) - let g:RubyDebugger.frames = [{ 'bla' : 'bla' }] - call g:RubyDebugger.next() - call g:TU.equal([], g:RubyDebugger.frames, "Frames should be cleaned", a:test) - - let g:RubyDebugger.frames = [{ 'bla' : 'bla' }] - call g:RubyDebugger.step() - call g:TU.equal([], g:RubyDebugger.frames, "Frames should be cleaned", a:test) - - let g:RubyDebugger.frames = [{ 'bla' : 'bla' }] - call g:RubyDebugger.continue() - call g:TU.equal([], g:RubyDebugger.frames, "Frames should be cleaned", a:test) - - let g:RubyDebugger.frames = [{ 'bla' : 'bla' }] - call g:RubyDebugger.exit() - call g:TU.equal([], g:RubyDebugger.frames, "Frames should be cleaned", a:test) -endfunction - - - - -let s:Tests.variables = {} - -function! s:Tests.variables.before_all() - call s:Mock.mock_debugger() -endfunction - - -function! s:Tests.variables.after_all() - call s:Mock.unmock_debugger() -endfunction - - -function! s:Tests.variables.before() - let g:RubyDebugger.breakpoints = [] - let g:RubyDebugger.frames = [] - let g:RubyDebugger.variables = {} - call g:RubyDebugger.queue.empty() - call s:Server._stop_server(s:rdebug_port) - call s:Server._stop_server(s:debugger_port) -endfunction - - -function! s:Tests.variables.test_should_open_window_without_got_variables(test) - call g:RubyDebugger.open_variables() - call g:TU.ok(s:variables_window.is_open(), "Variables window should be opened", a:test) - call g:TU.equal(bufwinnr("%"), s:variables_window.get_number(), "Focus should be into the variables window", a:test) - call g:TU.equal(getline(1), s:variables_window.title, "First line should be name", a:test) - exe 'close' -endfunction - - -" TODO: Now, variables are localized after receiving or -" in ruby_debugger.rb. I don't know how to test them there from here. -"function! s:Tests.variables.test_should_init_variables_after_breakpoint(test) -" let filename = s:Mock.mock_file() -" -" let cmd = '' -" call writefile([ cmd ], s:tmp_file) -" call g:RubyDebugger.receive_command() -" -" call g:TU.equal("VarParent", g:RubyDebugger.variables.type, "Root variable should be initialized", a:test) -" call g:TU.equal(5, len(g:RubyDebugger.variables.children), "4 variables should be initialized", a:test) -" call g:TU.equal(4, len(filter(copy(g:RubyDebugger.variables.children), 'v:val.type == "VarParent"')), "3 Parent variables should be initialized", a:test) -" call g:TU.equal(1, len(filter(copy(g:RubyDebugger.variables.children), 'v:val.type == "VarChild"')), "1 Child variable should be initialized", a:test) -" -" call s:Mock.unmock_file(filename) -"endfunction - - -function! s:Tests.variables.test_should_open_variables_window(test) - call g:RubyDebugger.send_command('var local') - - call g:RubyDebugger.open_variables() - call g:TU.ok(s:variables_window.is_open(), "Variables window should opened", a:test) - call g:TU.equal(bufwinnr("%"), s:variables_window.get_number(), "Focus should be into the variables window", a:test) - call g:TU.equal(getline(1), s:variables_window.title, "First line should be name", a:test) - call g:TU.match(getline(2), '|+self', "Second line should be 'self' variable", a:test) - call g:TU.match(getline(3), '|-some_local', "Third line should be a local variable", a:test) - call g:TU.match(getline(4), '|+array', "4-th line should be an array", a:test) - call g:TU.match(getline(5), '|+quoted_hash', "5-th line should be a hash", a:test) - call g:TU.match(getline(6), '`+hash', "6-th line should be a hash", a:test) - - exe 'close' -endfunction - - -function! s:Tests.variables.test_should_close_variables_window_after_opening(test) - call g:RubyDebugger.send_command('var local') - - call g:RubyDebugger.open_variables() - call g:RubyDebugger.open_variables() - call g:TU.ok(!s:variables_window.is_open(), "Variables window should be closed", a:test) -endfunction - - -function! s:Tests.variables.test_should_open_instance_subvariable(test) - call g:RubyDebugger.send_command('var local') - call g:RubyDebugger.open_variables() - exe 'normal 2G' - - call s:window_variables_activate_node() - call g:TU.ok(s:variables_window.is_open(), "Variables window should opened", a:test) - call g:TU.match(getline(2), '|\~self', "Second line should be opened 'self' variable", a:test) - call g:TU.match(getline(3), '| |+self_array', "Third line should be closed array subvariable", a:test) - call g:TU.match(getline(4), '| |-self_local', "4-th line should be local subvariable", a:test) - call g:TU.match(getline(5), '| `+array', "5-th line should be array", a:test) - call g:TU.match(getline(6), '|-some_local', "6-th line should be local variable", a:test) - - exe 'close' -endfunction - - -function! s:Tests.variables.test_should_open_instance_subvariable_with_quotes(test) - call g:RubyDebugger.send_command('var local') - call g:RubyDebugger.open_variables() - exe 'normal 5G' - - call s:window_variables_activate_node() - call g:TU.ok(s:variables_window.is_open(), "Variables window should opened", a:test) - call g:TU.match(getline(5), '|\~quoted_hash', "5-th line should be hash variable", a:test) - call g:TU.match(getline(6), "| `-'quoted'", "6-th line should be quoted variable", a:test) - - exe 'close' -endfunction - - -function! s:Tests.variables.test_should_close_instance_subvariable(test) - call g:RubyDebugger.send_command('var local') - call g:RubyDebugger.open_variables() - exe 'normal 2G' - - call s:window_variables_activate_node() - call s:window_variables_activate_node() - call g:TU.ok(s:variables_window.is_open(), "Variables window should opened", a:test) - call g:TU.match(getline(2), '|+self', "Second line should be closed 'self' variable", a:test) - - exe 'close' -endfunction - - -function! s:Tests.variables.test_should_open_last_variable_in_list(test) - call g:RubyDebugger.send_command('var local') - call g:RubyDebugger.open_variables() - exe 'normal 6G' - - call s:window_variables_activate_node() - call g:TU.match(getline(6), '`\~hash', "5-th line should be opened hash", a:test) - call g:TU.match(getline(7), ' |-hash_local', "6 line should be local subvariable", a:test) - call g:TU.match(getline(8), ' `+hash_array', "7-th line should be array subvariable", a:test) - - exe 'close' -endfunction - - -function! s:Tests.variables.test_should_open_childs_of_array(test) - call g:RubyDebugger.send_command('var local') - call g:RubyDebugger.open_variables() - exe 'normal 4G' - call s:window_variables_activate_node() - call g:TU.match(getline(4), '|\~array', '4-th line should be opened array', a:test) - call g:TU.match(getline(5), '| |-\[0\]', '5 line should be local subvariable', a:test) - call g:TU.match(getline(6), '| `+\[1\]', '6-th line should be array subvariable', a:test) - - exe 'close' -endfunction - - -function! s:Tests.variables.test_should_clear_variables_after_movement_command(test) - let g:RubyDebugger.variables = { 'bla' : 'bla' } - call g:RubyDebugger.next() - call g:TU.equal({}, g:RubyDebugger.variables, "Variables should be cleaned", a:test) - - let g:RubyDebugger.variables = { 'bla' : 'bla' } - call g:RubyDebugger.step() - call g:TU.equal({}, g:RubyDebugger.variables, "Variables should be cleaned", a:test) - - let g:RubyDebugger.variables = { 'bla' : 'bla' } - call g:RubyDebugger.continue() - call g:TU.equal({}, g:RubyDebugger.variables, "Variables should be cleaned", a:test) - - let g:RubyDebugger.variables = { 'bla' : 'bla' } - call g:RubyDebugger.exit() - call g:TU.equal({}, g:RubyDebugger.variables, "Variables should be cleaned", a:test) -endfunction - - -function! s:Tests.variables.test_should_open_correct_variable_if_variable_has_repeated_name(test) - call g:RubyDebugger.send_command('var local') - call g:RubyDebugger.open_variables() - exe 'normal 2G' - call s:window_variables_activate_node() - exe 'normal 7G' - call s:window_variables_activate_node() - - call g:TU.match(getline(5), '| `+array', "5-th line should be closed array", a:test) - call g:TU.match(getline(6), '|-some_local', "6-th line should be local variable", a:test) - call g:TU.match(getline(7), '|\~array', '7-th line should be opened array', a:test) - call g:TU.match(getline(8), '| |-\[0\]', '8 line should be local subvariable', a:test) - call g:TU.match(getline(9), '| `+\[1\]', '9-th line should be array subvariable', a:test) - - exe 'close' -endfunction - -" Test for issue #6 -"function! s:Tests.variables.test_should_update_opened_variables_on_next_suspend(test) -" call g:RubyDebugger.send_command('var local') -" call g:RubyDebugger.open_variables() -" exe 'normal 2G' -" call s:window_variables_activate_node() -" exe 'normal 7G' -" call s:window_variables_activate_node() -" call g:RubyDebugger.next() -" call g:RubyDebugger.open_variables() -" call g:RubyDebugger.open_variables() -" -" call g:TU.equal(7, line("."), "Current line should = 7", a:test) -" call g:TU.match(getline(2), '|\~self', "Second line should be opened 'self' variable", a:test) -" call g:TU.match(getline(3), '| |+self_array', "Third line should be closed array subvariable", a:test) -" call g:TU.match(getline(4), '| |-self_updated', "4-th line should be local subvariable", a:test) -" call g:TU.match(getline(5), '| `+array', "5-th line should be closed array", a:test) -" call g:TU.match(getline(6), '|-some_local', "6-th line should be local variable", a:test) -" call g:TU.match(getline(7), '|\~array', '7-th line should be opened array', a:test) -" call g:TU.match(getline(8), '| `+\[0\]', '9-th line should be array subvariable', a:test) -" call g:TU.match(getline(9), '|+quoted_hash', '9-th line should be array subvariable', a:test) -" -" call g:RubyDebugger.open_variables() -" unlet s:Mock.next -" call s:Mock.unmock_file(s:Mock.file) -" -"endfunction - -let s:Tests.command = {} - -function! s:Tests.command.before_all() - call s:Mock.mock_debugger() -endfunction - - -function! s:Tests.command.after_all() - call s:Mock.unmock_debugger() -endfunction - - -function! s:Tests.command.test_some_user_command(test) - call g:RubyDebugger.send_command("p \"all users\"") - call g:TU.equal(1, s:Mock.evals, "It should return eval command", a:test) -endfunction - - - diff --git a/vim/bundle/vim-ruby-debugger/src/additionals/bin/socket b/vim/bundle/vim-ruby-debugger/src/additionals/bin/socket deleted file mode 100755 index bc38eb5d6b503039b65cb191637cee10e26b29cc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7865 zcmcgxeQcY>9X>m5a7#bZHb8(5oRUJiQKy9xwQOu@QuhP;k+x~+CvP45jbB4zd-m(D znObOP$_Q3OB@ja!V-yf#8WTvmj=ey^A&;9Q1_uk!mckf-16-#_RpD@8Mssz!%J%QkS#F-kUnJ+@(0?{aDiYrAm zvZ$NC2OP)=q$%Sd0Z0|37Dj6K27;97z!d6en<4|s3P|mR;6hklpg!tl-jASzEJH>I zg!NMIN7M*@BXpD@U<&oDgVG3oBkHDvfGI||<~=tK__<)pH+3gFo4Vt3x|6B=&TuXr zzD|`z)v|3%SFM+2*$$Rr{#3}t5L7F}Mfhj_BnbP({*yZq5`;{Hm@owimPeQV=RhA{ z02vQqJ4~q6iOD7dG5b9MLLT*Oqx5yiKNCrr_slKt4lMjfaR#wBbZYPw#BB3T8t>BB z^q1Ko$QC9L+92frmH^>vAQJyxA|amFc&^55FZInDAJh18jUUx`w#Ka*M>IC=$!TnB z{c4S$)%Y2WO@Hp!_$sY`P~*JDKh(Hh;|&^{`u1x4itf*4z>nM)2-4?M#T4;f#9JRR zxK0SmO7x^tR?dxPUCR;}YB3J6W??N~jof%LW#w~rT;$TRJ8V}tZaS3{89SRzXGJWX zO4%`2q@t;GuG_XVBIjni?UcybskrE|dvYjYSsZX$-)}7ATqAQb4rra*!z^1CsvYc~mp>!sjcGJ4JWwHIbGdIS!L6i1-5dd?I5% z_>7^iWen%nF~%UD!59-S#26E%fiWgvBV$aSYZ+s5%w>!TIG-^l=>o=R!8aIVaJDeU zL|x1njaWZ152EI zPGa`l2@yXgF+Jck67QFoo^a+8?~#}uaTX9~B&KJa7UJy^(?iZO;&zGYDW{#dMPho) z*+@KBVtUTmP8^b$9(35DlQk04lTL3f zFudl>z~4(}{QVot3y_3P)M1QOA2{OvH`>0m*g~zjhdvzQw_zFh?TecnU-y!;6 zyoP+(FAN6{G=RHrz@2u8c}R>O3^XvWJoMV({rxK%0%&si+h@UEQyA{(TY01yIZ{{< zaKpv*M~ePJ$ydB+E6n#TZU_!8ZU{Vv6{WAXq4X9yG#ELG0VGaN$Eb(Z*P$v^Bfl?F zD(o(a{N>0TVrD%uOV9kPTrP^f$kCJUqEsx zmu?@mZ~z6+nqUpfp;d@Pf8( z$JxbJFanD4Rax^$VfTp0FDSjPY6CsXRD~Db*IqaVP3Z|mM8_t`j*S#sCicBtj3BOo z;f@A&Gl1ryBG$eR{K3c>ws|lzq@p+XjC|q;#dL}#ijiT`@5Y?%i<~M%&iKZ~mKz+GgDX zKN`#yuqxUfUxe+Iw0-PTV|$wB9z^zF0&u8ZADKuVO_*hjyHl|+?q|N5}{PSr_;`c(p{lwHj(eKQ*Q3Y(5!eUnaa6# zG)~3!6NDSf@b%_-K{d|S?@=TwUVM$SQ9d`pyiv)+D-;m}`d0SFOmnVq-1AAb?+XOE zuiJ&E%}KBfd(4kNE2oDMb6=Gy;9Z5d=6iu4_g(KpxVK|@?h6^%zq9ZRC*Q*m?#s9b zyaaOS?m&>~rx9~c#B$s}1|gU%>3flnCZ^e@5yYE;k^ItuduLPVA@u1f$U(@fkUv2F z3ONm_##!KE$kmW$$P&l~NEc)W$#2of9A+$ zG~k~;R=Z&J>}CS-+0myaC?0o@a#<6*&~K(5)X&)P(nx4~biWKuZcnBu!JSZ(o6V>0 zXv$?{JVV4(=A6!avOC@s%jKJ5SvMJ8C(d60BmsYg7Oe|i7oN8O+bG|jRj9--H^%|r z6G(?3(n2h@apRiKWGbBdk`{eaMNRek>Z;)7!CArS9I~I!`3Z9U!lBOh>EucHm#0K@ z+IRluODBx=SA@e&x!zpd&g7aBcFN8sV?t;jz)&)kbi42ujwzRp^K)iZP4?9{)!($a zK9Oi@@{dEs0lygM=L4%67Fy@8Mt-|&;??JCBB~m5kbGFM!V0eR)z{bivE%f?E+25! zoY5RJ_t}yxgw@^;K_xO6Jq_)Fu=v9sy$I)ed)#OzVmGT|Zm4An+iN?U5#dzYwZn^A zm(Ovd2@y`D@?j^Mb3{1an?hj~yIG~#VP|vP#7mk67Iay=n|zhXbh{!dM07nask$<7?uv2+htTu|-K ze8P%mqp5^VD-tGCU1^h!c6Mg%9R}g}j4BmNmoZ-a@A2iJ@R@P0$$JCkTyZhW+84s1_wHMT(5bj@TAT|G=8d5CEr&&FrIz#jYZ8xN2BjkDl!44FU< zWe{TQb>QUDfrtM^{rw$y%xC*}LfHx)$B7BF#qb7%_Dmq}P6H4d-Jd*Zs!xE|&V&x8 z4V*Kk3{`Wn0eeMr7#ZDZPn!83gV(@>4u%&%!lbFX6leT@8WLiot2u{PgFAp056`rZ z`!&z-746_%VT^d}F^gl*gaK>__hXLKBV#^<{^Qu^oUE{i1u^N#@R$a(GH|_Qj=ITJ z>!QM{X0CqzTr67y{QVg*h_S`lK*dUbPM>ENODzsxW(@_Ol9OQX+8u zP#A*|f$N0AY9w(zP?)=HwO3P^w}fhbD-0(ia2_j6&#C#UFrNz63ygb(xtqp#7{%(1 zV)nsRau=@dniOB{);Vt!#%&G)=ZC`Ft*d#UaGk{FuS#5Mk}|Fmyd4}1Rf2E1u~1d9 zvhn%xmU1jqi7Q6OC36Gf!?J9MrVxAIk;GR($MuU8A5Iw8A~yc;VN-b{u&@hoLut_Fo4u&&TJ#SiA#l`YZfX#YgAhYD^sSynX&!F$LH>&k#;u zm+6UR?uVN-Hut^DfqBownK2FR+XQUJEAe*ChgyUn@{mS=5P}q-=lhBN9Y+EJUKVt)rDNkYU^0N)>^TA zT?g*|Eo*TFy1C7xil?nace*p$ZOPrb70vI&ZADL}+ji}E_=e_%&4LOm8Q)2?K*%k= z70>td^qP7is}{>@maJX0GGZCTYD{{p7I`#~wWu!-Z0*t&t6LYXuvRZwvM$nLbu4OK z5n-#@Hyi`9(O!$+9V#;9cMV}J-n44b%H?f>#|ZU#0JO^Q5-lxb-wO1H4R4nIw15M# zB~LS>Rw_Q9SU2ym*4l|Au7R>`-O*eQ2NSC+V>#bJ#6yt!DB?9-c|+vYeC}(8S1CWl zcr(;D8E?)xUvNf0q*QP$k4u!Ny=wK5#+x(xt;d_GKIwRK)Q2E%j%CGjY0HVG;@vi! zf9|K8N~#=)W>Cm)I&?fAwERTmCCjfx-VFWW$eU$ZI63Mk#*4KIog6c^JYZJb$yJc7 aWb=aNF!WX?X1NY-Rl=P+h5W>%n)PoI95j*u diff --git a/vim/bundle/vim-ruby-debugger/src/collector.rb b/vim/bundle/vim-ruby-debugger/src/collector.rb deleted file mode 100644 index 55884e9..0000000 --- a/vim/bundle/vim-ruby-debugger/src/collector.rb +++ /dev/null @@ -1,45 +0,0 @@ -class Collector - - def initialize(input, output) - @path = File.dirname(__FILE__) - @input_files = input.map{|i| @path + '/' + i} - @output_file = File.expand_path(@path + '/' + output) - @file = '' - end - - def accumulate! - read_file - save_file - end - - - protected - - def read_file - @file = "" - plan = @input_files.inject([]) {|sum, i| sum += File.read(i).split("\n") } - plan.each do |line| - @file += File.read(@path + '/' + line) - @file += "\n" - end - @file - end - - - def save_file - File.open(@output_file, 'w') do |file| - file.write(@file) - end - end - -end - - -plugin = Collector.new(['ruby_debugger_plugin_plan.txt'], '../plugin/ruby_debugger.vim') -plugin.accumulate! - -auto_load = Collector.new(['ruby_debugger_autoload_plan.txt'], '../autoload/ruby_debugger.vim') -auto_load.accumulate! - -with_tests = Collector.new(['ruby_debugger_autoload_plan.txt', 'ruby_test_plan.txt'], 'additionals/autoload/ruby_debugger.vim') -with_tests.accumulate! diff --git a/vim/bundle/vim-ruby-debugger/src/notifier b/vim/bundle/vim-ruby-debugger/src/notifier deleted file mode 100755 index fe4d0ed..0000000 --- a/vim/bundle/vim-ruby-debugger/src/notifier +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -while inotifywait -r -e create,modify,delete ruby_debugger/*.vim tests/*.vim; do - sleep 0.3 - ruby collector.rb -done diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/after.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/after.vim deleted file mode 100644 index 21ae143..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/after.vim +++ /dev/null @@ -1,45 +0,0 @@ -" *** Creating instances (start) - -if !exists("g:ruby_debugger_fast_sender") - let g:ruby_debugger_fast_sender = 0 -endif -if !exists("g:ruby_debugger_debug_mode") - let g:ruby_debugger_debug_mode = 0 -endif -" This variable allows to use built-in Ruby (see ':help ruby' and s:send_message_to_debugger function) -if !exists("g:ruby_debugger_builtin_sender") - if has("ruby") - let g:ruby_debugger_builtin_sender = 1 - else - let g:ruby_debugger_builtin_sender = 0 - endif -endif -if !exists("g:ruby_debugger_spec_path") - let g:ruby_debugger_spec_path = '/usr/bin/spec' -endif -if !exists("g:ruby_debugger_cucumber_path") - let g:ruby_debugger_cucumber_path = '/usr/bin/cucumber' -endif -if !exists("g:ruby_debugger_progname") - let g:ruby_debugger_progname = v:progname -endif -if !exists("g:ruby_debugger_default_script") - let g:ruby_debugger_default_script = 'script/server webrick' -endif -if !exists("g:ruby_debugger_no_maps") - let g:ruby_debugger_no_maps = 0 -endif - -" Creating windows -let s:variables_window = s:WindowVariables.new("variables", "Variables_Window") -let s:breakpoints_window = s:WindowBreakpoints.new("breakpoints", "Breakpoints_Window") -let s:frames_window = s:WindowFrames.new("frames", "Backtrace_Window") - -" Init logger. The plugin logs all its actions. If you have some troubles, -" this file can help -let RubyDebugger.logger = s:Logger.new(s:logger_file) -let s:variables_window.logger = RubyDebugger.logger -let s:breakpoints_window.logger = RubyDebugger.logger -let s:frames_window.logger = RubyDebugger.logger - -" *** Creating instances (end) diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/before.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/before.vim deleted file mode 100644 index 2a1278e..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/before.vim +++ /dev/null @@ -1,77 +0,0 @@ -" Init section - set default values, highlight colors - -let s:rdebug_port = 39767 -let s:debugger_port = 39768 -" hostname() returns something strange in Windows (E98BD9A419BB41D), so set hostname explicitly -let s:hostname = '127.0.0.1' "hostname() -" ~/.vim for Linux, vimfiles for Windows -let s:runtime_dir = expand(':h:h') -" File for communicating between intermediate Ruby script ruby_debugger.rb and -" this plugin -let s:tmp_file = s:runtime_dir . '/tmp/ruby_debugger' -let s:logger_file = s:runtime_dir . '/tmp/ruby_debugger_log' -let s:server_output_file = s:runtime_dir . '/tmp/ruby_debugger_output' -" Default id for sign of current line -let s:current_line_sign_id = 120 -let s:separator = "++vim-ruby-debugger separator++" -let s:sign_id = 0 - -" Create tmp directory if it doesn't exist -if !isdirectory(s:runtime_dir . '/tmp') - call mkdir(s:runtime_dir . '/tmp') -endif - -" Init breakpoint signs -hi def link Breakpoint Error -sign define breakpoint linehl=Breakpoint text=xx - -" Init current line signs -hi def link CurrentLine DiffAdd -sign define current_line linehl=CurrentLine text=>> - -" Loads this file. Required for autoloading the code for this plugin -fun! ruby_debugger#load_debugger() - if !s:check_prerequisites() - finish - endif -endf - -fun! ruby_debugger#statusline() - let is_running = g:RubyDebugger.is_running() - if is_running == 0 - return '' - endif - return '[ruby debugger running]' -endfunction - -" Check all requirements for the current plugin -fun! s:check_prerequisites() - let problems = [] - if v:version < 700 - call add(problems, "RubyDebugger: This plugin requires Vim >= 7.") - endif - if !has("clientserver") - call add(problems, "RubyDebugger: This plugin requires +clientserver option") - endif - if !executable("rdebug-ide") - call add(problems, "RubyDebugger: You don't have installed 'ruby-debug-ide' gem or executable 'rdebug-ide' can't be found in your PATH") - endif - if !(has("win32") || has("win64")) && !executable("lsof") - call add(problems, "RubyDebugger: You don't have 'lsof' installed or executable 'lsof' can't be found in your PATH") - endif - if g:ruby_debugger_builtin_sender && !has("ruby") - call add(problems, "RubyDebugger: You are trying to use built-in Ruby in Vim, but your Vim doesn't compiled with +ruby. Set g:ruby_debugger_builtin_sender = 0 in your .vimrc to resolve that issue.") - end - if empty(problems) - return 1 - else - for p in problems - echoerr p - endfor - return 0 - endif -endf - - -" End of init section - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/breakpoint.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/breakpoint.vim deleted file mode 100644 index 420056b..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/breakpoint.vim +++ /dev/null @@ -1,118 +0,0 @@ -" *** Breakpoint class (start) - -let s:Breakpoint = { 'id': 0 } - -" ** Public methods - -" Constructor of new brekpoint. Create new breakpoint and set sign. -function! s:Breakpoint.new(file, line) - let var = copy(self) - let var.file = a:file - let var.line = a:line - let s:Breakpoint.id += 1 - let var.id = s:Breakpoint.id - - call var._set_sign() - call s:log("Set breakpoint to: " . var.file . ":" . var.line) - return var -endfunction - - -" Destroyer of the breakpoint. It just sends commands to debugger and destroys -" sign, but you should manually remove it from breakpoints array -function! s:Breakpoint.delete() dict - call self._unset_sign() - call self._send_delete_to_debugger() -endfunction - - -" Add condition to breakpoint. If server is not running, just store it, it -" will be evaluated after starting the server -function! s:Breakpoint.add_condition(condition) dict - let self.condition = a:condition - if has_key(g:RubyDebugger, 'server') && g:RubyDebugger.server.is_running() && has_key(self, 'debugger_id') - call g:RubyDebugger.queue.add(self.condition_command()) - endif -endfunction - - - -" Send adding breakpoint message to debugger, if it is run -function! s:Breakpoint.send_to_debugger() dict - if has_key(g:RubyDebugger, 'server') && g:RubyDebugger.server.is_running() - call s:log("Server is running, so add command to Queue") - call g:RubyDebugger.queue.add(self.command()) - endif -endfunction - - -" Command for setting breakpoint (e.g.: 'break /path/to/file:23') -function! s:Breakpoint.command() dict - return 'break ' . self.file . ':' . self.line -endfunction - - -" Command for adding condition to breakpoin (e.g.: 'condition 1 x>5') -function! s:Breakpoint.condition_command() dict - return 'condition ' . self.debugger_id . ' ' . self.condition -endfunction - - -" Find and return breakpoint under cursor -function! s:Breakpoint.get_selected() dict - let line = getline(".") - let match = matchlist(line, '^\(\d\+\)') - let id = get(match, 1) - let breakpoints = filter(copy(g:RubyDebugger.breakpoints), "v:val.id == " . id) - if !empty(breakpoints) - return breakpoints[0] - else - return {} - endif -endfunction - - -" Output format for Breakpoints Window -function! s:Breakpoint.render() dict - let output = self.id . " " . (exists("self.debugger_id") ? self.debugger_id : '') . " " . self.file . ":" . self.line - if exists("self.condition") - let output .= " " . self.condition - endif - return output . "\n" -endfunction - - -" Open breakpoint in existed/new window -function! s:Breakpoint.open() dict - call s:jump_to_file(self.file, self.line) -endfunction - - -" ** Private methods - - -function! s:Breakpoint._set_sign() dict - if has("signs") - exe ":sign place " . self.id . " line=" . self.line . " name=breakpoint file=" . self.file - endif -endfunction - - -function! s:Breakpoint._unset_sign() dict - if has("signs") - exe ":sign unplace " . self.id - endif -endfunction - - -" Send deleting breakpoint message to debugger, if it is run -" (e.g.: 'delete 5') -function! s:Breakpoint._send_delete_to_debugger() dict - if has_key(g:RubyDebugger, 'server') && g:RubyDebugger.server.is_running() - let message = 'delete ' . self.debugger_id - call g:RubyDebugger.queue.add(message) - endif -endfunction - - -" *** Breakpoint class (end) diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/commands.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/commands.vim deleted file mode 100644 index 6c796ce..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/commands.vim +++ /dev/null @@ -1,186 +0,0 @@ -" *** RubyDebugger Commands (what debugger returns) - - -" -" -" Jump to file/line where execution was suspended, set current line sign and get local variables -function! RubyDebugger.commands.jump_to_breakpoint(cmd) dict - let attrs = s:get_tag_attributes(a:cmd) - call s:jump_to_file(attrs.file, attrs.line) - call s:log("Jumped to breakpoint " . attrs.file . ":" . attrs.line) - - if has("signs") - exe ":sign place " . s:current_line_sign_id . " line=" . attrs.line . " name=current_line file=" . attrs.file - endif -endfunction - - -" -" Show message error and jump to given file/line -function! RubyDebugger.commands.handle_exception(cmd) dict - let message_match = matchlist(a:cmd, 'message="\(.\{-}\)"') - call g:RubyDebugger.commands.jump_to_breakpoint(a:cmd) - echo "Exception message: " . s:unescape_html(message_match[1]) -endfunction - - -" -" Confirm setting of exception catcher -function! RubyDebugger.commands.set_exception(cmd) dict - let attrs = s:get_tag_attributes(a:cmd) - call s:log("Exception successfully set: " . attrs.exception) -endfunction - - -" -" Add debugger info to breakpoints (pid of debugger, debugger breakpoint's id) -" Assign rest breakpoints to debugger recursively, if there are breakpoints -" from old server runnings or not assigned breakpoints (e.g., if you at first -" set some breakpoints, and then run the debugger by :Rdebugger) -function! RubyDebugger.commands.set_breakpoint(cmd) - call s:log("Received the breakpoint message, will add PID and number of breakpoint to the Breakpoint object") - let attrs = s:get_tag_attributes(a:cmd) - let file_match = matchlist(attrs.location, '\(.*\):\(.*\)') - let pid = g:RubyDebugger.server.rdebug_pid - - " Find added breakpoint in array and assign debugger's info to it - for breakpoint in g:RubyDebugger.breakpoints - if expand(breakpoint.file) == expand(file_match[1]) && expand(breakpoint.line) == expand(file_match[2]) - call s:log("Found the Breakpoint object for " . breakpoint.file . ":" . breakpoint.line) - let breakpoint.debugger_id = attrs.no - let breakpoint.rdebug_pid = pid - call s:log("Added id: " . breakpoint.debugger_id . ", PID:" . breakpoint.rdebug_pid . " to Breakpoint") - if has_key(breakpoint, 'condition') - call breakpoint.add_condition(breakpoint.condition) - endif - endif - endfor - - call s:log("Breakpoint is set: " . file_match[1] . ":" . file_match[2]) - call g:RubyDebugger.queue.execute() -endfunction - - -" -" -" -" Assign list of got variables to parent variable and (optionally) show them -function! RubyDebugger.commands.set_variables(cmd) - let tags = s:get_tags(a:cmd) - let list_of_variables = [] - - " Create hash from list of tags - for tag in tags - let attrs = s:get_tag_attributes(tag) - let variable = s:Var.new(attrs) - call add(list_of_variables, variable) - endfor - - " If there is no variables, create unnamed root variable. Local variables - " will be chilren of this variable - if g:RubyDebugger.variables == {} - let g:RubyDebugger.variables = s:VarParent.new({'hasChildren': 'true'}) - let g:RubyDebugger.variables.is_open = 1 - let g:RubyDebugger.variables.children = [] - endif - - " If g:RubyDebugger.current_variable exists, then it contains parent - " variable of got subvariables. Assign them to it. - if has_key(g:RubyDebugger, 'current_variable') - let variable = g:RubyDebugger.current_variable - if variable != {} - call variable.add_childs(list_of_variables) - call s:log("Opening child variable: " . variable.attributes.objectId) - " Variables Window is always open if we got subvariables - call s:variables_window.open() - else - call s:log("Can't found variable") - endif - unlet g:RubyDebugger.current_variable - else - " Otherwise, assign them to unnamed root variable - if g:RubyDebugger.variables.children == [] - call g:RubyDebugger.variables.add_childs(list_of_variables) - call s:log("Initializing local variables") - if s:variables_window.is_open() - " show variables only if Variables Window is open - call s:variables_window.open() - endif - endif - endif - -endfunction - - -" -" Just show result of evaluation -function! RubyDebugger.commands.eval(cmd) - " rdebug-ide-gem doesn't escape attributes of tag properly, so we should not - " use usual attribute extractor here... - let match = matchlist(a:cmd, "") - echo "Evaluated expression:\n" . s:unescape_html(match[1]) ."\nResulted value is:\n" . match[2] . "\n" -endfunction - - -" -" Just show exception message -function! RubyDebugger.commands.processing_exception(cmd) - let attrs = s:get_tag_attributes(a:cmd) - let message = "RubyDebugger Exception, type: " . attrs.type . ", message: " . attrs.message - echo message - call s:log(message) -endfunction - - -" -" -" -" -" Assign all frames, fill Frames window by them -function! RubyDebugger.commands.trace(cmd) - let tags = s:get_tags(a:cmd) - let list_of_frames = [] - - " Create hash from list of tags - for tag in tags - let attrs = s:get_tag_attributes(tag) - let frame = s:Frame.new(attrs) - call add(list_of_frames, frame) - endfor - - let g:RubyDebugger.frames = list_of_frames - - if s:frames_window.is_open() - " show backtrace only if Backtrace Window is open - call s:frames_window.open() - endif -endfunction - - -" Error -" Just show error -function! RubyDebugger.commands.error(cmd) - let error_match = s:get_inner_tags(a:cmd) - if !empty(error_match) - let error = error_match[1] - echo "RubyDebugger Error: " . error - call s:log("Got error: " . error) - endif -endfunction - - -" Message -" Just show message -function! RubyDebugger.commands.message(cmd) - let message_match = s:get_inner_tags(a:cmd) - if !empty(message_match) - let message = message_match[1] - echo "RubyDebugger Message: " . message - call s:log("Got message: " . message) - endif -endfunction - - -" *** End of debugger Commands - - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/common.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/common.vim deleted file mode 100644 index bc36215..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/common.vim +++ /dev/null @@ -1,303 +0,0 @@ -" *** Common (global) functions - -" Split string of tags to List. E.g., -" -" will be splitted to -" [ '', '' ] -function! s:get_tags(cmd) - let tags = [] - let cmd = a:cmd - " Remove wrap tags - let inner_tags_match = s:get_inner_tags(cmd) - if !empty(inner_tags_match) - " Then find every tag and remove it from source string - let pattern = '<.\{-}\/>' - let inner_tags = inner_tags_match[1] - let tagmatch = matchlist(inner_tags, pattern) - while empty(tagmatch) == 0 - call add(tags, tagmatch[0]) - " These symbols are interpretated as special, we need to escape them - let tagmatch[0] = escape(tagmatch[0], '[]~*\') - " Remove it from source string - let inner_tags = substitute(inner_tags, tagmatch[0], '', '') - " Find next tag - let tagmatch = matchlist(inner_tags, pattern) - endwhile - endif - return tags -endfunction - - -" Converts command with relative path to absolute path. If given command -" contains relative path, it will try to use 'which' on it first, and if -" 'which' returns nothing, it will add current dir path to given command -function! s:get_escaped_absolute_path(command) - " Remove leading and trailing quotes - let given_path = a:command - let given_path = substitute(given_path, '"', '\"', "g") - let given_path = substitute(given_path, "^'", '', "g") - let given_path = substitute(given_path, "'$", '', "g") - if given_path[0] == '/' - let absolute_path = given_path - else - let parts = split(given_path) - let relative_command = remove(parts, 0) - let arguments = join(parts) - let absolute_command = "" - " I don't know Windows analogue for 'which', if you know - feel free to add it here - if !(has("win32") || has("win64")) - let absolute_command = s:strip(system('which ' . relative_command)) - endif - if absolute_command[0] != '/' - let absolute_command = getcwd() . '/' . relative_command - endif - let absolute_path = "\"'" . absolute_command . "' " . arguments . '"' - endif - return absolute_path -endfunction - - -" Return a string without leading and trailing spaces and linebreaks. -function! s:strip(input_string) - return substitute(substitute(a:input_string, "\n", '', 'g'), '(\s*\(.\{-}\)\s*', '\1', 'g') -endfunction - - -" Shortcut for g:RubyDebugger.logger.debug -function! s:log(string) - call g:RubyDebugger.logger.put(a:string) -endfunction - - -" Return match of inner tags without wrap tags. E.g.: -" mathes only -function! s:get_inner_tags(cmd) - return matchlist(a:cmd, '^<.\{-}>\(.\{-}\)<\/.\{-}>$') -endfunction - - -" Return Dict of attributes. -" E.g., from it returns -" {'name' : 'a', 'value' : 'b'} -function! s:get_tag_attributes(cmd) - let attributes = {} - let cmd = a:cmd - " Find type of used quotes (" or ') - let quote_match = matchlist(cmd, "\\w\\+=\\(.\\)") - let quote = empty(quote_match) ? "\"" : escape(quote_match[1], "'\"") - let pattern = "\\(\\w\\+\\)=" . quote . "\\(.\\{-}\\)" . quote - " Find every attribute and remove it from source string - let attrmatch = matchlist(cmd, pattern) - while !empty(attrmatch) - " Values of attributes can be escaped by HTML entities, unescape them - let attributes[attrmatch[1]] = s:unescape_html(attrmatch[2]) - " These symbols are interpretated as special, we need to escape them - let attrmatch[0] = escape(attrmatch[0], '[]~*\') - " Remove it from source string - let cmd = substitute(cmd, attrmatch[0], '', '') - " Find next attribute - let attrmatch = matchlist(cmd, pattern) - endwhile - return attributes -endfunction - - -" Unescape HTML entities -function! s:unescape_html(html) - let result = substitute(a:html, "&", "\\&", "g") - let result = substitute(result, """, "\"", "g") - let result = substitute(result, "<", "<", "g") - let result = substitute(result, ">", ">", "g") - return result -endfunction - - -function! s:quotify(exp) - let quoted = a:exp - let quoted = substitute(quoted, "\"", "\\\\\"", 'g') - return quoted -endfunction - - -" Get filename of current buffer -function! s:get_filename() - return expand("%:p") -endfunction - - -" Send message to debugger. This function should never be used explicitly, -" only through g:RubyDebugger.send_command function -function! s:send_message_to_debugger(message) - call s:log("Sending a message to ruby_debugger.rb: '" . a:message . "'") - if g:ruby_debugger_fast_sender - call s:log("Trying to use experimental 'fast_sender'") - let cmd = s:runtime_dir . "/bin/socket " . s:hostname . " " . s:debugger_port . " \"" . a:message . "\"" - call s:log("Executing command: " . cmd) - call system(cmd) - else - if g:ruby_debugger_builtin_sender - call s:log("Using Vim built-in Ruby to send message") -ruby << RUBY - require 'socket' - attempts = 0 - a = nil - host = VIM::evaluate("s:hostname") - port = VIM::evaluate("s:debugger_port") - message = VIM::evaluate("a:message").gsub("\\\"", '"') - begin - a = TCPSocket.open(host, port) - a.puts(message) - a.close - rescue Errno::ECONNREFUSED - attempts += 1 - if attempts < 400 - sleep 0.05 - retry - else - puts("#{host}:#{port} can not be opened") - exit - end - ensure - a.close if a && !a.closed? - end -RUBY - else - let script = "ruby -e \"require 'socket'; " - let script .= "attempts = 0; " - let script .= "a = nil; " - let script .= "begin; " - let script .= "a = TCPSocket.open('" . s:hostname . "', " . s:debugger_port . "); " - let script .= "a.puts(%q[" . substitute(substitute(a:message, '[', '\[', 'g'), ']', '\]', 'g') . "]);" - let script .= "a.close; " - let script .= "rescue Errno::ECONNREFUSED; " - let script .= "attempts += 1; " - let script .= "if attempts < 400; " - let script .= "sleep 0.05; " - let script .= "retry; " - let script .= "else; " - let script .= "puts('" . s:hostname . ":" . s:debugger_port . " can not be opened'); " - let script .= "exit; " - let script .= "end; " - let script .= "ensure; " - let script .= "a.close if a && !a.closed?; " - let script .= "end; \"" - call s:log("Using system-wide Ruby to send message, the command is: " . script) - let output = system(script) - call s:log("Command has returned following output: " . output) - if output =~ 'can not be opened' - call s:log("Can't send a message to rdebug - port is not opened") - endif - endif - endif -endfunction - - -function! s:unplace_sign_of_current_line() - if has("signs") - exe ":sign unplace " . s:current_line_sign_id - endif -endfunction - - -" Remove all variables of current line, remove current line sign. Usually it -" is needed before next/step/cont commands -function! s:clear_current_state() - call s:unplace_sign_of_current_line() - let g:RubyDebugger.variables = {} - let g:RubyDebugger.frames = [] - " Clear variables and frames window (just show our empty variables Dict) - if s:variables_window.is_open() - call s:variables_window.open() - endif - if s:frames_window.is_open() - call s:frames_window.open() - endif -endfunction - - -" Open given file and jump to given line -" (stolen from NERDTree) -function! s:jump_to_file(file, line) - "if the file is already open in this tab then just stick the cursor in it - let window_number = bufwinnr('^' . a:file . '$') - if window_number != -1 - exe window_number . "wincmd w" - else - " Check if last accessed window is usable to use it - " Usable window - not quickfix, explorer, modified, etc - if !s:is_window_usable(winnr("#")) - exe s:first_normal_window() . "wincmd w" - else - " If it is usable, jump to it - exe 'wincmd p' - endif - exe "edit " . a:file - endif - exe "normal " . a:line . "G" -endfunction - - -" Return 1 if window is usable (not quickfix, explorer, modified, only one -" window, ...) -function! s:is_window_usable(winnumber) - "If there is only one window (winnr("$") - windows count) - if winnr("$") ==# 1 - return 0 - endif - - " Current window number - let oldwinnr = winnr() - - " Switch to given window and check it - exe a:winnumber . "wincmd p" - let specialWindow = getbufvar("%", '&buftype') != '' || getwinvar('%', '&previewwindow') - let modified = &modified - - exe oldwinnr . "wincmd p" - - "if it is a special window, e.g. quickfix or another explorer plugin - if specialWindow - return 0 - endif - - if &hidden - return 1 - endif - - " If this window is modified, but there is another opened window with - " current file, return 1. Otherwise - 0 - return !modified || s:buf_in_windows(winbufnr(a:winnumber)) >= 2 -endfunction - - -" Determine the number of windows open to this buffer number. -function! s:buf_in_windows(buffer_number) - let count = 0 - let window_number = 1 - while 1 - let buffer_number = winbufnr(window_number) - if buffer_number < 0 - break - endif - if buffer_number ==# a:buffer_number - let count = count + 1 - endif - let window_number = window_number + 1 - endwhile - - return count -endfunction - - -" Find first 'normal' window (not quickfix, explorer, etc) -function! s:first_normal_window() - let i = 1 - while i <= winnr("$") - let bnum = winbufnr(i) - if bnum != -1 && getbufvar(bnum, '&buftype') ==# '' && !getwinvar(i, '&previewwindow') - return i - endif - let i += 1 - endwhile - return -1 -endfunction diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/exception.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/exception.vim deleted file mode 100644 index 562913e..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/exception.vim +++ /dev/null @@ -1,33 +0,0 @@ -" *** Exception class (start) -" These are ruby exceptions we catch with 'catch Exception' command -" (:RdbCatch) - -let s:Exception = { } - -" ** Public methods - -" Constructor of new exception. -function! s:Exception.new(name) - let var = copy(self) - let var.name = a:name - call s:log("Trying to set exception: " . var.name) - call g:RubyDebugger.queue.add(var.command()) - return var -endfunction - - -" Command for setting exception (e.g.: 'catch NameError') -function! s:Exception.command() dict - return 'catch ' . self.name -endfunction - - -" Output format for Breakpoints Window -function! s:Exception.render() dict - return self.name -endfunction - -" *** Exception class (end) - - - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/frame.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/frame.vim deleted file mode 100644 index ba8557d..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/frame.vim +++ /dev/null @@ -1,70 +0,0 @@ -" *** Frame class (start) - -let s:Frame = { } - -" ** Public methods - -" Constructor of new frame. -" Create new frame and set sign to it. -function! s:Frame.new(attrs) - let var = copy(self) - let var.no = a:attrs.no - let var.file = a:attrs.file - let var.line = a:attrs.line - if has_key(a:attrs, 'current') - let var.current = (a:attrs.current == 'true') - else - let var.current = 0 - endif - "let s:sign_id += 1 - "let var.sign_id = s:sign_id - "call var._set_sign() - return var -endfunction - - -" Find and return frame under cursor -function! s:Frame.get_selected() dict - let line = getline(".") - let match = matchlist(line, '^\(\d\+\)') - let no = get(match, 1) - let frames = filter(copy(g:RubyDebugger.frames), "v:val.no == " . no) - if !empty(frames) - return frames[0] - else - return {} - endif -endfunction - - -" Output format for Frame Window -function! s:Frame.render() dict - return self.no . (self.current ? ' Current' : ''). " " . self.file . ":" . self.line . "\n" -endfunction - - -" Open frame in existed/new window -function! s:Frame.open() dict - call s:jump_to_file(self.file, self.line) -endfunction - - -" ** Private methods - -function! s:Frame._set_sign() dict - if has("signs") - exe ":sign place " . self.sign_id . " line=" . self.line . " name=frame file=" . self.file - endif -endfunction - - -function! s:Frame._unset_sign() dict - if has("signs") - exe ":sign unplace " . self.sign_id - endif -endfunction - - -" *** Frame class (end) - - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/init.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/init.vim deleted file mode 100644 index 15ec473..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/init.vim +++ /dev/null @@ -1,29 +0,0 @@ -if exists("g:ruby_debugger_loaded") - finish -endif - -if !exists("g:ruby_debugger_no_maps") || !g:ruby_debugger_no_maps - noremap b :call ruby_debugger#load_debugger() call g:RubyDebugger.toggle_breakpoint() - noremap v :call ruby_debugger#load_debugger() call g:RubyDebugger.open_variables() - noremap m :call ruby_debugger#load_debugger() call g:RubyDebugger.open_breakpoints() - noremap t :call ruby_debugger#load_debugger() call g:RubyDebugger.open_frames() - noremap s :call ruby_debugger#load_debugger() call g:RubyDebugger.step() - noremap f :call ruby_debugger#load_debugger() call g:RubyDebugger.finish() - noremap n :call ruby_debugger#load_debugger() call g:RubyDebugger.next() - noremap c :call ruby_debugger#load_debugger() call g:RubyDebugger.continue() - noremap e :call ruby_debugger#load_debugger() call g:RubyDebugger.exit() - noremap d :call ruby_debugger#load_debugger() call g:RubyDebugger.remove_breakpoints() -endif - -command! -nargs=* -complete=file Rdebugger call ruby_debugger#load_debugger() | call g:RubyDebugger.start() -command! -nargs=0 RdbStop call g:RubyDebugger.stop() -command! -nargs=1 RdbCommand call g:RubyDebugger.send_command_wrapper() -command! -nargs=0 RdbTest call g:RubyDebugger.run_test() -command! -nargs=0 RdbTestSingle call g:RubyDebugger.run_test(" -l " . line(".")) -command! -nargs=1 RdbEval call g:RubyDebugger.eval() -command! -nargs=1 RdbCond call g:RubyDebugger.conditional_breakpoint() -command! -nargs=1 RdbCatch call g:RubyDebugger.catch_exception() -command! -nargs=0 RdbLog call ruby_debugger#load_debugger() | call g:RubyDebugger.show_log() - -let g:ruby_debugger_loaded = 1 - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/logger.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/logger.vim deleted file mode 100644 index e0f9341..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/logger.vim +++ /dev/null @@ -1,30 +0,0 @@ -" *** Logger class (start) - -let s:Logger = {} - -function! s:Logger.new(file) - let new_variable = copy(self) - let new_variable.file = a:file - call writefile([], new_variable.file) - return new_variable -endfunction - - -" Log datetime and then message. It logs only if debug mode is enabled -" TODO It outputs a bunch of spaces at the front of the entry - fix that. -function! s:Logger.put(string) dict - if g:ruby_debugger_debug_mode - let string = 'Vim plugin, ' . strftime("%H:%M:%S") . ': ' . a:string - exec 'redir >> ' . g:RubyDebugger.logger.file - silent call s:Logger.silent_echo(s:strip(string)) - exec 'redir END' - endif -endfunction - -function! s:Logger.silent_echo(string) - echo a:string -endfunction - -" *** Logger class (end) -" -" diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/public.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/public.vim deleted file mode 100644 index 2599b19..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/public.vim +++ /dev/null @@ -1,279 +0,0 @@ -" *** Public interface (start) - -let RubyDebugger = { 'commands': {}, 'variables': {}, 'settings': {}, 'breakpoints': [], 'frames': [], 'exceptions': [] } -let g:RubyDebugger.queue = s:Queue.new() - - -" Run debugger server. It takes one optional argument with path to debugged -" ruby script ('script/server webrick' by default) -function! RubyDebugger.start(...) dict - call s:log("Executing :Rdebugger...") - let g:RubyDebugger.server = s:Server.new(s:hostname, s:rdebug_port, s:debugger_port, s:runtime_dir, s:tmp_file, s:server_output_file) - let script_string = a:0 && !empty(a:1) ? a:1 : g:ruby_debugger_default_script - let params = a:0 && a:0 > 1 && !empty(a:2) ? a:2 : [] - echo "Loading debugger..." - call g:RubyDebugger.server.start(s:get_escaped_absolute_path(script_string), params) - - let g:RubyDebugger.exceptions = [] - for breakpoint in g:RubyDebugger.breakpoints - call g:RubyDebugger.queue.add(breakpoint.command()) - endfor - call g:RubyDebugger.queue.add('start') - echo "Debugger started" - call g:RubyDebugger.queue.execute() -endfunction - - -" Stop running server. -function! RubyDebugger.stop() dict - if has_key(g:RubyDebugger, 'server') - call g:RubyDebugger.server.stop() - endif -endfunction - -function! RubyDebugger.is_running() - if has_key(g:RubyDebugger, 'server') - return g:RubyDebugger.server.is_running() - endif - return 0 -endfunction - -" This function receives commands from the debugger. When ruby_debugger.rb -" gets output from rdebug-ide, it writes it to the special file and 'kick' -" the plugin by remotely calling RubyDebugger.receive_command(), e.g.: -" vim --servername VIM --remote-send 'call RubyDebugger.receive_command()' -" That's why +clientserver is required -" This function analyzes the special file and gives handling to right command -function! RubyDebugger.receive_command() dict - let file_contents = join(readfile(s:tmp_file), "") - call s:log("Received command: " . file_contents) - let commands = split(file_contents, s:separator) - for cmd in commands - if !empty(cmd) - if match(cmd, '') != -1 - call g:RubyDebugger.commands.set_variables(cmd) - elseif match(cmd, '') != -1 - call g:RubyDebugger.commands.error(cmd) - elseif match(cmd, '') != -1 - call g:RubyDebugger.commands.message(cmd) - elseif match(cmd, '') != -1 - call g:RubyDebugger.commands.trace(cmd) - endif - endif - endfor - call g:RubyDebugger.queue.after_hook() - call g:RubyDebugger.queue.execute() -endfunction - - -function! RubyDebugger.send_command_wrapper(command) - call g:RubyDebugger.send_command(a:command) -endfunction - -" We set function this way, because we want have possibility to mock it by -" other function in tests -let RubyDebugger.send_command = function("send_message_to_debugger") - - -" Open variables window -function! RubyDebugger.open_variables() dict - call s:variables_window.toggle() - call s:log("Opened variables window") - call g:RubyDebugger.queue.execute() -endfunction - - -" Open breakpoints window -function! RubyDebugger.open_breakpoints() dict - call s:breakpoints_window.toggle() - call s:log("Opened breakpoints window") - call g:RubyDebugger.queue.execute() -endfunction - - -" Open frames window -function! RubyDebugger.open_frames() dict - call s:frames_window.toggle() - call s:log("Opened frames window") - call g:RubyDebugger.queue.execute() -endfunction - - -" Set/remove breakpoint at current position. If argument -" is given, it will set conditional breakpoint (argument is condition) -function! RubyDebugger.toggle_breakpoint(...) dict - let line = line(".") - let file = s:get_filename() - call s:log("Trying to toggle a breakpoint in the file " . file . ":" . line) - let existed_breakpoints = filter(copy(g:RubyDebugger.breakpoints), 'v:val.line == ' . line . ' && v:val.file == "' . escape(file, '\') . '"') - " If breakpoint with current file/line doesn't exist, create it. Otherwise - - " remove it - if empty(existed_breakpoints) - call s:log("There is no already set breakpoint, so create new one") - let breakpoint = s:Breakpoint.new(file, line) - call add(g:RubyDebugger.breakpoints, breakpoint) - call s:log("Added Breakpoint object to RubyDebugger.breakpoints array") - call breakpoint.send_to_debugger() - else - call s:log("There is already set breakpoint presented, so delete it") - let breakpoint = existed_breakpoints[0] - call filter(g:RubyDebugger.breakpoints, 'v:val.id != ' . breakpoint.id) - call s:log("Removed Breakpoint object from RubyDebugger.breakpoints array") - call breakpoint.delete() - endif - " Update info in Breakpoints window - if s:breakpoints_window.is_open() - call s:breakpoints_window.open() - exe "wincmd p" - endif - call g:RubyDebugger.queue.execute() -endfunction - - -" Remove all breakpoints -function! RubyDebugger.remove_breakpoints() dict - for breakpoint in g:RubyDebugger.breakpoints - call breakpoint.delete() - endfor - let g:RubyDebugger.breakpoints = [] - call g:RubyDebugger.queue.execute() -endfunction - - -" Eval the passed in expression -function! RubyDebugger.eval(exp) dict - let quoted = s:quotify(a:exp) - call g:RubyDebugger.queue.add("eval " . quoted) - call g:RubyDebugger.queue.execute() -endfunction - - -" Sets conditional breakpoint where cursor is placed -function! RubyDebugger.conditional_breakpoint(exp) dict - let line = line(".") - let file = s:get_filename() - let existed_breakpoints = filter(copy(g:RubyDebugger.breakpoints), 'v:val.line == ' . line . ' && v:val.file == "' . escape(file, '\') . '"') - " If breakpoint with current file/line doesn't exist, create it. Otherwise - - " remove it - if empty(existed_breakpoints) - echo "You can set condition only to already set breakpoints. Move cursor to set breakpoint and add condition" - else - let breakpoint = existed_breakpoints[0] - let quoted = s:quotify(a:exp) - call breakpoint.add_condition(quoted) - " Update info in Breakpoints window - if s:breakpoints_window.is_open() - call s:breakpoints_window.open() - exe "wincmd p" - endif - call g:RubyDebugger.queue.execute() - endif -endfunction - - -" Catch all exceptions with given name -function! RubyDebugger.catch_exception(exp) dict - if has_key(g:RubyDebugger, 'server') && g:RubyDebugger.server.is_running() - let quoted = s:quotify(a:exp) - let exception = s:Exception.new(quoted) - call add(g:RubyDebugger.exceptions, exception) - if s:breakpoints_window.is_open() - call s:breakpoints_window.open() - exe "wincmd p" - endif - call g:RubyDebugger.queue.execute() - else - echo "Sorry, but you can set Exceptional Breakpoints only with running debugger" - endif -endfunction - - -" Next -function! RubyDebugger.next() dict - call g:RubyDebugger.queue.add("next") - call s:clear_current_state() - call s:log("Step over") - call g:RubyDebugger.queue.execute() -endfunction - - -" Step -function! RubyDebugger.step() dict - call g:RubyDebugger.queue.add("step") - call s:clear_current_state() - call s:log("Step into") - call g:RubyDebugger.queue.execute() -endfunction - - -" Finish -function! RubyDebugger.finish() dict - call g:RubyDebugger.queue.add("finish") - call s:clear_current_state() - call s:log("Step out") - call g:RubyDebugger.queue.execute() -endfunction - - -" Continue -function! RubyDebugger.continue() dict - call g:RubyDebugger.queue.add("cont") - call s:clear_current_state() - call s:log("Continue") - call g:RubyDebugger.queue.execute() -endfunction - - -" Exit -function! RubyDebugger.exit() dict - call g:RubyDebugger.queue.add("exit") - call s:clear_current_state() - call g:RubyDebugger.queue.execute() -endfunction - - -" Show output log of Ruby script -function! RubyDebugger.show_log() dict - exe "view " . s:server_output_file - setlocal autoread - " Per gorkunov's request - setlocal wrap - setlocal nonumber - if exists(":AnsiEsc") - exec ":AnsiEsc" - endif -endfunction - - -" Debug current opened test -function! RubyDebugger.run_test(...) dict - let file = s:get_filename() - if file =~ '_spec\.rb$' - let line = a:0 && a:0 > 0 && !empty(a:1) ? a:1 : " " - call g:RubyDebugger.start(g:ruby_debugger_spec_path . ' ' . file . line) - elseif file =~ '\.feature$' - call g:RubyDebugger.start(g:ruby_debugger_cucumber_path . ' ' . file) - elseif file =~ '_test\.rb$' - call g:RubyDebugger.start(file, ['-Itest']) - endif -endfunction - - -" *** Public interface (end) - - - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/queue.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/queue.vim deleted file mode 100644 index 3c7ed54..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/queue.vim +++ /dev/null @@ -1,49 +0,0 @@ -" *** Queue class (start) - -let s:Queue = {} - -" ** Public methods - -" Constructor of new queue. -function! s:Queue.new() dict - let var = copy(self) - let var.queue = [] - let var.after = "" - return var -endfunction - - -" Execute next command in the queue and remove it from queue -function! s:Queue.execute() dict - if !empty(self.queue) - call s:log("Executing queue") - let message = join(self.queue, s:separator) - call self.empty() - call g:RubyDebugger.send_command(message) - endif -endfunction - - -" Execute 'after' hook only if queue is empty -function! s:Queue.after_hook() dict - if self.after != "" && empty(self.queue) - call self.after() - endif -endfunction - - -function! s:Queue.add(element) dict - call s:log("Adding '" . a:element . "' to queue") - call add(self.queue, a:element) -endfunction - - -function! s:Queue.empty() dict - let self.queue = [] -endfunction - - -" *** Queue class (end) - - - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/server.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/server.vim deleted file mode 100644 index b4fc02f..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/server.vim +++ /dev/null @@ -1,141 +0,0 @@ -" *** Server class (start) - -let s:Server = {} - -" ** Public methods - -" Constructor of new server. Just inits it, not runs -function! s:Server.new(hostname, rdebug_port, debugger_port, runtime_dir, tmp_file, output_file) dict - let var = copy(self) - let var.hostname = a:hostname - let var.rdebug_port = a:rdebug_port - let var.debugger_port = a:debugger_port - let var.runtime_dir = a:runtime_dir - let var.tmp_file = a:tmp_file - let var.output_file = a:output_file - call s:log("Initializing Server object, with variables: hostname: " . var.hostname . ", rdebug_port: " . var.rdebug_port . ", debugger_port: " . var.debugger_port . ", runtime_dir: " . var.runtime_dir . ", tmp_file: " . var.tmp_file . ", output_file: " . var.output_file) - return var -endfunction - - -" Start the server. It will kill any listeners on given ports before. -function! s:Server.start(script, params) dict - call s:log("Starting Server, command: " . a:script) - call s:log("Trying to kill all old servers first") - call self._stop_server(self.rdebug_port) - call self._stop_server(self.debugger_port) - call s:log("Servers are killed, trying to start new servers") - " Remove leading and trailing quotes - let script_name = substitute(a:script, "\\(^['\"]\\|['\"]$\\)", '', 'g') - let rdebug = 'rdebug-ide ' . join(a:params, ' ') . ' -p ' . self.rdebug_port . ' -- ' . script_name - let os = has("win32") || has("win64") ? 'win' : 'posix' - " Example - ruby ~/.vim/bin/ruby_debugger.rb 39767 39768 vim VIM /home/anton/.vim/tmp/ruby_debugger posix - let debugger_parameters = ' ' . self.hostname . ' ' . self.rdebug_port . ' ' . self.debugger_port - let debugger_parameters .= ' ' . g:ruby_debugger_progname . ' ' . v:servername . ' "' . self.tmp_file - let debugger_parameters .= '" ' . os . ' ' . g:ruby_debugger_debug_mode . ' ' . s:logger_file - - " Start in background - if has("win32") || has("win64") - silent exe '! start ' . rdebug - let debugger = 'ruby "' . expand(self.runtime_dir . "/bin/ruby_debugger.rb") . '"' . debugger_parameters - silent exe '! start ' . debugger - else - let cmd = rdebug . ' > ' . self.output_file . ' 2>&1 &' - call s:log("Executing command: ". cmd) - call system(cmd) - let debugger_cmd = 'ruby ' . expand(self.runtime_dir . "/bin/ruby_debugger.rb") . debugger_parameters . ' &' - call s:log("Executing command: ". debugger_cmd) - call system(debugger_cmd) - endif - - " Set PIDs of processes - call s:log("Now we need to store PIDs of servers, retrieving them: ") - let self.rdebug_pid = self._get_pid(self.rdebug_port, 1) - let self.debugger_pid = self._get_pid(self.debugger_port, 1) - call s:log("Server PIDs are: rdebug-ide: " . self.rdebug_pid . ", ruby_debugger.rb: " . self.debugger_pid) - - call s:log("Debugger is successfully started") -endfunction - - -" Kill servers and empty PIDs -function! s:Server.stop() dict - call self._kill_process(self.rdebug_pid) - call self._kill_process(self.debugger_pid) - let self.rdebug_pid = "" - let self.debugger_pid = "" -endfunction - - -" Return 1 if processes with set PID exist. -function! s:Server.is_running() dict - return (self._get_pid(self.rdebug_port, 0) =~ '^\d\+$') && (self._get_pid(self.debugger_port, 0) =~ '^\d\+$') -endfunction - - -" ** Private methods - - -" Get PID of process, that listens given port on given host. If must_get_pid -" parameter is true, it will try to get PID for 10 seconds. -function! s:Server._get_pid(port, must_get_pid) - call s:log("Trying to find PID of process on " . a:port . " port, must_get_pid = " . a:must_get_pid) - let attempt = 0 - let pid = self._get_pid_attempt(a:port) - while a:must_get_pid && pid == "" && attempt < 1000 - sleep 10m - let attempt += 1 - let pid = self._get_pid_attempt(a:port) - endwhile - call s:log("PID - " . pid . ", found by " . attempt . " repeats") - return pid -endfunction - - -" Just try to get PID of process and return empty string if it was -" unsuccessful -function! s:Server._get_pid_attempt(port) - call s:log("Trying to find listener of port " . a:port) - if has("win32") || has("win64") - let netstat = system("netstat -anop tcp") - let pid_match = matchlist(netstat, ':' . a:port . '\s.\{-}LISTENING\s\+\(\d\+\)') - let pid = len(pid_match) > 0 ? pid_match[1] : "" - elseif executable('lsof') - let cmd = "lsof -i tcp:" . a:port . " | grep LISTEN | awk '{print $2}'" - call s:log("Executing command: " . cmd) - let pid = system(cmd) - let pid = substitute(pid, '\n', '', '') - else - let pid = "" - endif - call s:log("Found pid - " . pid) - return pid -endfunction - - -" Kill listener of given host/port -function! s:Server._stop_server(port) dict - let pid = self._get_pid(a:port, 0) - if pid =~ '^\d\+$' - call self._kill_process(pid) - endif -endfunction - - -" Kill process with given PID -function! s:Server._kill_process(pid) dict - let message = "Killing server with pid " . a:pid - call s:log(message) - echo message - let cmd = "ruby -e 'Process.kill(9," . a:pid . ")'" - call s:log("Executing command: " . cmd) - call system(cmd) - call s:log("Sleeping 100m...") - sleep 100m - call s:log("Killed server with pid: " . a:pid) -endfunction - - -" *** Server class (end) - - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/var.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/var.vim deleted file mode 100644 index 2c75431..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/var.vim +++ /dev/null @@ -1,34 +0,0 @@ -" *** Var proxy class (start) - -let s:Var = { 'id' : 0 } - -" ** Public methods - -" This is a proxy method for creating new variable -function! s:Var.new(attrs) - if has_key(a:attrs, 'hasChildren') && a:attrs['hasChildren'] == 'true' - return s:VarParent.new(a:attrs) - else - return s:VarChild.new(a:attrs) - end -endfunction - - -" Get variable under cursor -function! s:Var.get_selected() - let line = getline(".") - " Get its id - it is last in the string - let match = matchlist(line, '.*\t\(\d\+\)$') - let id = get(match, 1) - if id - let variable = g:RubyDebugger.variables.find_variable({'id' : id}) - return variable - else - return {} - endif -endfunction - - -" *** Var proxy class (end) - - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/var_child.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/var_child.vim deleted file mode 100644 index 0910f4a..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/var_child.vim +++ /dev/null @@ -1,164 +0,0 @@ -" *** VarChild class (start) - -let s:VarChild = {} - -" ** Public methods - -" Constructs new variable without childs -function! s:VarChild.new(attrs) - let new_variable = copy(self) - let new_variable.attributes = a:attrs - let new_variable.parent = {} - let new_variable.level = 0 - let new_variable.type = "VarChild" - let s:Var.id += 1 - let new_variable.id = s:Var.id - return new_variable -endfunction - - -" Renders data of the variable -function! s:VarChild.render() - return self._render(0, 0, [], len(self.parent.children) ==# 1) -endfunction - - -" VarChild can't be opened because it can't have children. But VarParent can -function! s:VarChild.open() - return 0 -endfunction - - -" VarChild can't be closed because it can't have children. But VarParent can -function! s:VarChild.close() - return 0 -endfunction - - -" VarChild can't be parent. But VarParent can. If Var have hasChildren == -" true, then it is parent -function! s:VarChild.is_parent() - return has_key(self.attributes, 'hasChildren') && get(self.attributes, 'hasChildren') ==# 'true' -endfunction - - -" Output format for Variables Window -function! s:VarChild.to_s() - return get(self.attributes, "name", "undefined") . "\t" . get(self.attributes, "type", "undefined") . "\t" . get(self.attributes, "value", "undefined") . "\t" . get(self, "id", "0") -endfunction - - -" Find and return variable by given Dict of attrs, e.g.: {'name' : 'var1'} -function! s:VarChild.find_variable(attrs) - if self._match_attributes(a:attrs) - return self - else - return {} - endif -endfunction - - -" Find and return array of variables that match given Dict of attrs -function! s:VarChild.find_variables(attrs) - let variables = [] - if self._match_attributes(a:attrs) - call add(variables, self) - endif - return variables -endfunction - - -" ** Private methods - - -" Recursive function, that renders Variable and all its childs (if they are -" presented). Stolen from NERDTree -function! s:VarChild._render(depth, draw_text, vertical_map, is_last_child) - let output = "" - if a:draw_text ==# 1 - let tree_parts = '' - - " get all the leading spaces and vertical tree parts for this line - if a:depth > 1 - for j in a:vertical_map[0:-2] - if j ==# 1 - let tree_parts = tree_parts . '| ' - else - let tree_parts = tree_parts . ' ' - endif - endfor - endif - - " get the last vertical tree part for this line which will be different - " if this node is the last child of its parent - if a:is_last_child - let tree_parts = tree_parts . '`' - else - let tree_parts = tree_parts . '|' - endif - - " smack the appropriate dir/file symbol on the line before the file/dir - " name itself - if self.is_parent() - if self.is_open - let tree_parts = tree_parts . '~' - else - let tree_parts = tree_parts . '+' - endif - else - let tree_parts = tree_parts . '-' - endif - let line = tree_parts . self.to_s() - let output = output . line . "\n" - - endif - - if self.is_parent() && self.is_open - if len(self.children) > 0 - - " draw all the nodes children except the last - let last_index = len(self.children) - 1 - if last_index > 0 - for i in self.children[0:last_index - 1] - let output = output . i._render(a:depth + 1, 1, add(copy(a:vertical_map), 1), 0) - endfor - endif - - " draw the last child, indicating that it IS the last - let output = output . self.children[last_index]._render(a:depth + 1, 1, add(copy(a:vertical_map), 0), 1) - - endif - endif - - return output - -endfunction - - -" Return 1 if *all* given attributes (pairs key/value) match to current -" variable -function! s:VarChild._match_attributes(attrs) - let conditions = 1 - for attr in keys(a:attrs) - if has_key(self.attributes, attr) - " If current key is contained in attributes of variable (they were - " attributes in tag, then trying to match there. - let conditions = conditions && self.attributes[attr] == a:attrs[attr] - elseif has_key(self, attr) - " Otherwise, if current key is contained in auxiliary attributes of the - " variable, trying to match there - let conditions = conditions && self[attr] == a:attrs[attr] - else - " Otherwise, this variable is not match - let conditions = 0 - break - endif - endfor - return conditions -endfunction - - -" *** VarChild class (end) - - - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/var_parent.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/var_parent.vim deleted file mode 100644 index 1d7ac4c..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/var_parent.vim +++ /dev/null @@ -1,122 +0,0 @@ -" *** VarParent class (start) - -" Inherits VarParent from VarChild -let s:VarParent = copy(s:VarChild) - -" ** Public methods - - -" Initializes new variable with childs -function! s:VarParent.new(attrs) - if !has_key(a:attrs, 'hasChildren') || a:attrs['hasChildren'] != 'true' - throw "RubyDebug: VarParent must be initialized with hasChildren = true" - endif - let new_variable = copy(self) - let new_variable.attributes = a:attrs - let new_variable.parent = {} - let new_variable.is_open = 0 - let new_variable.level = 0 - let new_variable.children = [] - let new_variable.type = "VarParent" - let s:Var.id += 1 - let new_variable.id = s:Var.id - return new_variable -endfunction - - -" Open variable, init its children and display them -function! s:VarParent.open() - let self.is_open = 1 - call self._init_children() - return 0 -endfunction - - -" Close variable and display it -function! s:VarParent.close() - let self.is_open = 0 - call s:variables_window.display() - if has_key(g:RubyDebugger, "current_variable") - unlet g:RubyDebugger.current_variable - endif - return 0 -endfunction - - -" Renders data of the variable -function! s:VarParent.render() - return self._render(0, 0, [], len(self.children) ==# 1) -endfunction - - - -" Add childs to the variable. You always should use this method instead of -" explicit assigning to children property (like 'add(self.children, variables)') -function! s:VarParent.add_childs(childs) - " If children are given by array, extend self.children by this array - if type(a:childs) == type([]) - for child in a:childs - let child.parent = self - let child.level = self.level + 1 - endfor - call extend(self.children, a:childs) - else - " Otherwise, add child to self.children - let a:childs.parent = self - let child.level = self.level + 1 - call add(self.children, a:childs) - end -endfunction - - -" Find and return variable by given Dict of attrs, e.g.: {'name' : 'var1'} -" If current variable doesn't match these attributes, try to find in children -function! s:VarParent.find_variable(attrs) - if self._match_attributes(a:attrs) - return self - else - for child in self.children - let result = child.find_variable(a:attrs) - if result != {} - return result - endif - endfor - endif - return {} -endfunction - - -" Find and return array of variables that match given Dict of attrs. -" Try to match current variable and its children -function! s:VarParent.find_variables(attrs) - let variables = [] - if self._match_attributes(a:attrs) - call add(variables, self) - endif - for child in self.children - call extend(variables, child.find_variables(a:attrs)) - endfor - return variables -endfunction - - -" ** Private methods - - -" Update children of the variable -function! s:VarParent._init_children() - " Remove all the current child nodes - let self.children = [] - - " Get children - if has_key(self.attributes, 'objectId') - let g:RubyDebugger.current_variable = self - call g:RubyDebugger.queue.add('var instance ' . self.attributes.objectId) - endif - -endfunction - - -" *** VarParent class (end) - - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/window.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/window.vim deleted file mode 100644 index f811f90..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/window.vim +++ /dev/null @@ -1,191 +0,0 @@ -" *** Window class (start). Abstract Class for creating window. -" Must be inherited. Mostly, stolen from the NERDTree. - -let s:Window = {} -let s:Window['next_buffer_number'] = 1 -let s:Window['position'] = 'botright' -let s:Window['size'] = 10 - -" ** Public methods - -" Constructs new window -function! s:Window.new(name, title) dict - let new_variable = copy(self) - let new_variable.name = a:name - let new_variable.title = a:title - return new_variable -endfunction - - -" Clear all data from window -function! s:Window.clear() dict - silent 1,$delete _ -endfunction - - -" Close window -function! s:Window.close() dict - if !self.is_open() - throw "RubyDebug: Window " . self.name . " is not open" - endif - - if winnr("$") != 1 - call self.focus() - close - exe "wincmd p" - else - " If this is only one window, just quit - :q - endif - call s:log("Closed window with name: " . self.name) -endfunction - - -" Get window number -function! s:Window.get_number() dict - if self._exist_for_tab() - return bufwinnr(self._buf_name()) - else - return -1 - endif -endfunction - - -" Display data to the window -function! s:Window.display() - call s:log("Start displaying data in window with name: " . self.name) - call self.focus() - setlocal modifiable - - let current_line = line(".") - let current_column = col(".") - let top_line = line("w0") - - call self.clear() - - call self._insert_data() - call self._restore_view(top_line, current_line, current_column) - - setlocal nomodifiable - call s:log("Complete displaying data in window with name: " . self.name) -endfunction - - -" Put cursor to the window -function! s:Window.focus() dict - exe self.get_number() . " wincmd w" - call s:log("Set focus to window with name: " . self.name) -endfunction - - -" Return 1 if window is opened -function! s:Window.is_open() dict - return self.get_number() != -1 -endfunction - - -" Open window and display data (stolen from NERDTree) -function! s:Window.open() dict - if !self.is_open() - " create the window - silent exec self.position . ' ' . self.size . ' new' - - if !self._exist_for_tab() - " If the window is not opened/exists, create new - call self._set_buf_name(self._next_buffer_name()) - silent! exec "edit " . self._buf_name() - " This function does not exist in Window class and should be declared in - " descendants - call self.bind_mappings() - else - " Or just jump to opened buffer - silent! exec "buffer " . self._buf_name() - endif - - " set buffer options - setlocal winfixheight - setlocal noswapfile - setlocal buftype=nofile - setlocal nowrap - setlocal foldcolumn=0 - setlocal nobuflisted - setlocal nospell - setlocal nolist - iabc - setlocal cursorline - setfiletype ruby_debugger_window - call s:log("Opened window with name: " . self.name) - endif - - if has("syntax") && exists("g:syntax_on") && !has("syntax_items") - call self.setup_syntax_highlighting() - endif - - call self.display() -endfunction - - -" Open/close window -function! s:Window.toggle() dict - call s:log("Toggling window with name: " . self.name) - if self._exist_for_tab() && self.is_open() - call self.close() - else - call self.open() - end -endfunction - - -" ** Private methods - - -" Return buffer name, that is stored in tab variable -function! s:Window._buf_name() dict - return t:window_{self.name}_buf_name -endfunction - - -" Return 1 if the window exists in current tab -function! s:Window._exist_for_tab() dict - return exists("t:window_" . self.name . "_buf_name") -endfunction - - -" Insert data to the window -function! s:Window._insert_data() dict - let old_p = @p - " Put data to the register and then show it by 'put' command - let @p = self.render() - silent exe "normal \"pP" - let @p = old_p - call s:log("Inserted data to window with name: " . self.name) -endfunction - - -" Calculate correct name for the window -function! s:Window._next_buffer_name() dict - let name = self.name . s:Window.next_buffer_number - let s:Window.next_buffer_number += 1 - return name -endfunction - - -" Restore the view -function! s:Window._restore_view(top_line, current_line, current_column) dict - let old_scrolloff=&scrolloff - let &scrolloff=0 - call cursor(a:top_line, 1) - normal! zt - call cursor(a:current_line, a:current_column) - let &scrolloff = old_scrolloff - call s:log("Restored view of window with name: " . self.name) -endfunction - - -function! s:Window._set_buf_name(name) dict - let t:window_{self.name}_buf_name = a:name -endfunction - - -" *** Window class (end) - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/window_breakpoints.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/window_breakpoints.vim deleted file mode 100644 index 961f7fa..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/window_breakpoints.vim +++ /dev/null @@ -1,70 +0,0 @@ -" *** WindowBreakpoints class (start) - -" Inherits WindowBreakpoints from Window -let s:WindowBreakpoints = copy(s:Window) - -" ** Public methods - -function! s:WindowBreakpoints.bind_mappings() - nnoremap <2-leftmouse> :call window_breakpoints_activate_node() - nnoremap o :call window_breakpoints_activate_node() - nnoremap d :call window_breakpoints_delete_node() -endfunction - - -" Returns string that contains all breakpoints (for Window.display()) -function! s:WindowBreakpoints.render() dict - let breakpoints = "" - let breakpoints .= self.title . "\n" - for breakpoint in g:RubyDebugger.breakpoints - let breakpoints .= breakpoint.render() - endfor - let exceptions = map(copy(g:RubyDebugger.exceptions), 'v:val.render()') - let breakpoints .= "\nException breakpoints: " . join(exceptions, ", ") - return breakpoints -endfunction - - -" TODO: Is there some way to call s:WindowBreakpoints.activate_node from mapping -" command? -" Open breakpoint under cursor -function! s:window_breakpoints_activate_node() - let breakpoint = s:Breakpoint.get_selected() - if breakpoint != {} - call breakpoint.open() - endif -endfunction - - -" Delete breakpoint under cursor -function! s:window_breakpoints_delete_node() - let breakpoint = s:Breakpoint.get_selected() - if breakpoint != {} - call breakpoint.delete() - call filter(g:RubyDebugger.breakpoints, "v:val.id != " . breakpoint.id) - call s:breakpoints_window.open() - endif -endfunction - - -" Add syntax highlighting -function! s:WindowBreakpoints.setup_syntax_highlighting() dict - execute "syn match rdebugTitle #" . self.title . "#" - - syn match rdebugId "^\d\+\s" contained nextgroup=rdebugDebuggerId - syn match rdebugDebuggerId "\d*\s" contained nextgroup=rdebugFile - syn match rdebugFile ".*:" contained nextgroup=rdebugLine - syn match rdebugLine "\d\+" contained - - syn match rdebugWrapper "^\d\+.*" contains=rdebugId transparent - - hi def link rdebugId Directory - hi def link rdebugDebuggerId Type - hi def link rdebugFile Normal - hi def link rdebugLine Special -endfunction - - -" *** WindowBreakpoints class (end) - - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/window_frames.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/window_frames.vim deleted file mode 100644 index c014716..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/window_frames.vim +++ /dev/null @@ -1,53 +0,0 @@ -" *** WindowFrames class (start) - -" Inherits WindowFrames from Window -let s:WindowFrames = copy(s:Window) - -" ** Public methods - -function! s:WindowFrames.bind_mappings() - nnoremap <2-leftmouse> :call window_frames_activate_node() - nnoremap o :call window_frames_activate_node() -endfunction - - -" Returns string that contains all frames (for Window.display()) -function! s:WindowFrames.render() dict - let frames = "" - let frames .= self.title . "\n" - for frame in g:RubyDebugger.frames - let frames .= frame.render() - endfor - return frames -endfunction - - -" Open frame under cursor -function! s:window_frames_activate_node() - let frame = s:Frame.get_selected() - if frame != {} - call frame.open() - endif -endfunction - - -" Add syntax highlighting -function! s:WindowFrames.setup_syntax_highlighting() dict - execute "syn match rdebugTitle #" . self.title . "#" - - syn match rdebugId "^\d\+\s" contained nextgroup=rdebugFile - syn match rdebugFile ".*:" contained nextgroup=rdebugLine - syn match rdebugLine "\d\+" contained - - syn match rdebugWrapper "^\d\+.*" contains=rdebugId transparent - - hi def link rdebugId Directory - hi def link rdebugFile Normal - hi def link rdebugLine Special -endfunction - - -" *** WindowFrames class (end) - - - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/window_variables.vim b/vim/bundle/vim-ruby-debugger/src/ruby_debugger/window_variables.vim deleted file mode 100644 index 707d291..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger/window_variables.vim +++ /dev/null @@ -1,72 +0,0 @@ -" *** WindowVariables class (start) - -" Inherits variables window from abstract window class -let s:WindowVariables = copy(s:Window) - -" ** Public methods - -function! s:WindowVariables.bind_mappings() - nnoremap <2-leftmouse> :call window_variables_activate_node() - nnoremap o :call window_variables_activate_node()" -endfunction - - -" Returns string that contains all variables (for Window.display()) -function! s:WindowVariables.render() dict - let variables = self.title . "\n" - let variables .= (g:RubyDebugger.variables == {} ? '' : g:RubyDebugger.variables.render()) - return variables -endfunction - - -" TODO: Is there some way to call s:WindowVariables.activate_node from mapping -" command? -" Expand/collapse variable under cursor -function! s:window_variables_activate_node() - let variable = s:Var.get_selected() - if variable != {} && variable.type == "VarParent" - if variable.is_open - call variable.close() - else - call variable.open() - endif - endif - call g:RubyDebugger.queue.execute() -endfunction - - -" Add syntax highlighting -function! s:WindowVariables.setup_syntax_highlighting() - execute "syn match rdebugTitle #" . self.title . "#" - - syn match rdebugPart #[| `]\+# - syn match rdebugPartFile #[| `]\+-# contains=rdebugPart nextgroup=rdebugChild contained - syn match rdebugChild #.\{-}\t# nextgroup=rdebugType contained - - syn match rdebugClosable #[| `]\+\~# contains=rdebugPart nextgroup=rdebugParent contained - syn match rdebugOpenable #[| `]\++# contains=rdebugPart nextgroup=rdebugParent contained - syn match rdebugParent #.\{-}\t# nextgroup=rdebugType contained - - syn match rdebugType #.\{-}\t# nextgroup=rdebugValue contained - syn match rdebugValue #.*\t#he=e-1 nextgroup=rdebugId contained - syn match rdebugId #.*# contained - - syn match rdebugParentLine '[| `]\+[+\~].*' contains=rdebugClosable,rdebugOpenable transparent - syn match rdebugChildLine '[| `]\+-.*' contains=rdebugPartFile transparent - - hi def link rdebugTitle Identifier - hi def link rdebugClosable Type - hi def link rdebugOpenable Title - hi def link rdebugPart Special - hi def link rdebugPartFile Type - hi def link rdebugChild Normal - hi def link rdebugParent Directory - hi def link rdebugType Type - hi def link rdebugValue Special - hi def link rdebugId Ignore -endfunction - - -" *** WindowVariables class (end) - - diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger_autoload_plan.txt b/vim/bundle/vim-ruby-debugger/src/ruby_debugger_autoload_plan.txt deleted file mode 100644 index 01faf16..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger_autoload_plan.txt +++ /dev/null @@ -1,18 +0,0 @@ -ruby_debugger/before.vim -ruby_debugger/common.vim -ruby_debugger/queue.vim -ruby_debugger/public.vim -ruby_debugger/commands.vim -ruby_debugger/window.vim -ruby_debugger/window_variables.vim -ruby_debugger/window_breakpoints.vim -ruby_debugger/window_frames.vim -ruby_debugger/var.vim -ruby_debugger/var_child.vim -ruby_debugger/var_parent.vim -ruby_debugger/logger.vim -ruby_debugger/breakpoint.vim -ruby_debugger/exception.vim -ruby_debugger/frame.vim -ruby_debugger/server.vim -ruby_debugger/after.vim diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_debugger_plugin_plan.txt b/vim/bundle/vim-ruby-debugger/src/ruby_debugger_plugin_plan.txt deleted file mode 100644 index 7467ff7..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_debugger_plugin_plan.txt +++ /dev/null @@ -1 +0,0 @@ -ruby_debugger/init.vim diff --git a/vim/bundle/vim-ruby-debugger/src/ruby_test_plan.txt b/vim/bundle/vim-ruby-debugger/src/ruby_test_plan.txt deleted file mode 100644 index 48c8d82..0000000 --- a/vim/bundle/vim-ruby-debugger/src/ruby_test_plan.txt +++ /dev/null @@ -1,8 +0,0 @@ -tests/framework.vim -tests/mock.vim -tests/server.vim -tests/breakpoint.vim -tests/exceptions.vim -tests/frames.vim -tests/variables.vim -tests/command.vim diff --git a/vim/bundle/vim-ruby-debugger/src/socket.c b/vim/bundle/vim-ruby-debugger/src/socket.c deleted file mode 100644 index 3c6faad..0000000 --- a/vim/bundle/vim-ruby-debugger/src/socket.c +++ /dev/null @@ -1,78 +0,0 @@ -#include /* perror() and errno */ -#include /* required by getprotobyname() */ - -#include -#include /* both required by socket() */ - -#include /* define sockaddr_in */ - -#include -#include -#include -#include - -#include - -extern int errno; - -int main(int argc, char **argv) { - - if(argc != 4) { - fprintf(stderr, "Wrong number of arguments: %d instead of 3\n", argc - 1); - return EXIT_FAILURE; - } - - struct protoent *protocol; - protocol = getprotobyname("tcp"); - if(!protocol) { - perror("getprotobyname()"); - return(errno); - } - - int sd; /* our socket descriptor */ - sd = socket(PF_INET, SOCK_STREAM, protocol->p_proto); - if(!sd) { - perror("socket()"); - return(errno); - } - - struct sockaddr_in socketaddr; - memset(&socketaddr, 0, sizeof(socketaddr)); /* initialize it */ - socketaddr.sin_family = AF_INET; /* set the family type to Internet */ - socketaddr.sin_port = htons(atoi(argv[2])); - - extern int h_errno; - struct hostent *hostaddr; - hostaddr = gethostbyname(argv[1]); - if(!hostaddr) { - fprintf(stderr, "gethostbyname(): %s\n", hstrerror(h_errno)); - return(h_errno); - } - memcpy(&socketaddr.sin_addr, hostaddr->h_addr, hostaddr->h_length); - - int rval; - int attempts = 0; - struct timespec ts = { .tv_sec = 0, .tv_nsec = 50000000 }; - do { - rval = connect(sd, (struct sockaddr *) &socketaddr, sizeof(socketaddr)); - attempts += 1; - nanosleep(&ts, NULL); - } while (rval == -1 && attempts < 400); - - if (rval == -1) { - perror("connect()"); - return(errno); - } - - rval = send(sd, argv[3], strlen(argv[3]), NULL); - if (rval == -1) { - perror("send()"); - return(errno); - } - - close(sd); - return EXIT_SUCCESS; - -} - - diff --git a/vim/bundle/vim-ruby-debugger/src/tests/breakpoint.vim b/vim/bundle/vim-ruby-debugger/src/tests/breakpoint.vim deleted file mode 100644 index a4b0230..0000000 --- a/vim/bundle/vim-ruby-debugger/src/tests/breakpoint.vim +++ /dev/null @@ -1,215 +0,0 @@ -let s:Tests.breakpoint = {} - -function! s:Tests.breakpoint.before_all() - call s:Mock.mock_debugger() -endfunction - - -function! s:Tests.breakpoint.after_all() - call s:Mock.unmock_debugger() -endfunction - - -function! s:Tests.breakpoint.before() - let s:Breakpoint.id = 0 - let g:RubyDebugger.frames = [] - let g:RubyDebugger.exceptions = [] - let g:RubyDebugger.breakpoints = [] - let g:RubyDebugger.variables = {} - call g:RubyDebugger.queue.empty() - call s:Server._stop_server(s:rdebug_port) - call s:Server._stop_server(s:debugger_port) - silent exe "only" -endfunction - - -function! s:Tests.breakpoint.test_should_set_breakpoint(test) - exe "Rdebugger" - let filename = s:Mock.mock_file() - let file_pattern = substitute(filename, '[\/\\]', '[\\\/\\\\]', "g") - - call g:RubyDebugger.toggle_breakpoint() - let breakpoint = get(g:RubyDebugger.breakpoints, 0) - call g:TU.equal(1, breakpoint.id, "Id of first breakpoint should == 1", a:test) - call g:TU.match(breakpoint.file, file_pattern, "File should be set right", a:test) - call g:TU.equal(1, breakpoint.line, "Line should be set right", a:test) - " TODO: Find way to test sign - call g:TU.equal(g:RubyDebugger.server.rdebug_pid, breakpoint.rdebug_pid, "Breakpoint should be assigned to running server", a:test) - call g:TU.equal(1, breakpoint.debugger_id, "Breakpoint should get number from debugger", a:test) - call s:Mock.unmock_file(filename) -endfunction - - -function! s:Tests.breakpoint.test_should_add_all_unassigned_breakpoints_to_running_server(test) - let filename = s:Mock.mock_file() - " Write 3 lines of text and set 3 breakpoints (on every line) - exe "normal iblablabla" - exe "normal oblabla" - exe "normal obla" - exe "normal gg" - exe "write" - call g:RubyDebugger.toggle_breakpoint() - exe "normal j" - call g:RubyDebugger.toggle_breakpoint() - exe "normal j" - call g:RubyDebugger.toggle_breakpoint() - - " Lets suggest that some breakpoint was assigned to old server - let g:RubyDebugger.breakpoints[1].rdebug_pid = 'bla' - - call g:TU.equal(3, len(g:RubyDebugger.breakpoints), "3 breakpoints should be set", a:test) - exe "Rdebugger" - call g:TU.equal(3, s:Mock.breakpoints, "3 breakpoints should be assigned", a:test) - for breakpoint in g:RubyDebugger.breakpoints - call g:TU.equal(g:RubyDebugger.server.rdebug_pid, breakpoint.rdebug_pid, "Breakpoint should have PID of running server", a:test) - endfor - call s:Mock.unmock_file(filename) -endfunction - - -function! s:Tests.breakpoint.test_should_remove_all_breakpoints(test) - let filename = s:Mock.mock_file() - " Write 3 lines of text and set 3 breakpoints (on every line) - exe "normal iblablabla" - exe "normal oblabla" - exe "normal obla" - exe "normal gg" - exe "write" - call g:RubyDebugger.toggle_breakpoint() - exe "normal j" - call g:RubyDebugger.toggle_breakpoint() - exe "normal j" - call g:RubyDebugger.toggle_breakpoint() - call g:TU.equal(3, len(g:RubyDebugger.breakpoints), "3 breakpoints should be set", a:test) - - call g:RubyDebugger.remove_breakpoints() - - call g:TU.equal(0, len(g:RubyDebugger.breakpoints), "Breakpoints should be removed", a:test) - - call s:Mock.unmock_file(filename) -endfunction - - -function! s:Tests.breakpoint.test_jump_to_breakpoint_by_breakpoint(test) - call s:Tests.breakpoint.jump_to_breakpoint('breakpoint', a:test) -endfunction - - -function! s:Tests.breakpoint.test_jump_to_breakpoint_by_suspended(test) - call s:Tests.breakpoint.jump_to_breakpoint('suspended', a:test) -endfunction - - -function! s:Tests.breakpoint.test_delete_breakpoint(test) - exe "Rdebugger" - let filename = s:Mock.mock_file() - call g:RubyDebugger.toggle_breakpoint() - call g:RubyDebugger.toggle_breakpoint() - - call g:TU.ok(empty(g:RubyDebugger.breakpoints), "Breakpoint should be removed", a:test) - call g:TU.equal(0, s:Mock.breakpoints, "0 breakpoints should be assigned", a:test) - - call s:Mock.unmock_file(filename) -endfunction - - -function! s:Tests.breakpoint.jump_to_breakpoint(cmd, test) - let filename = s:Mock.mock_file() - let file_pattern = substitute(filename, '[\/\\]', '[\\\/\\\\]', "g") - - " Write 2 lines and set current line to second line. We will jump to first - " line - exe "normal iblablabla" - exe "normal oblabla" - exe "write" - - call g:TU.equal(2, line("."), "Current line before jumping is second", a:test) - - let cmd = '<' . a:cmd . ' file="' . filename . '" line="1" />' - call writefile([ cmd ], s:tmp_file) - call g:RubyDebugger.receive_command() - - call g:TU.equal(1, line("."), "Current line before jumping is first", a:test) - call g:TU.match(expand("%"), file_pattern, "Jumped to correct file", a:test) - - call s:Mock.unmock_file(filename) -endfunction - - -function! s:Tests.breakpoint.test_should_open_window_without_got_breakpoints(test) - call g:RubyDebugger.open_breakpoints() - - call g:TU.ok(s:breakpoints_window.is_open(), "Breakpoints window should opened", a:test) - call g:TU.equal(bufwinnr("%"), s:breakpoints_window.get_number(), "Focus should be into the breakpoints window", a:test) - call g:TU.equal(getline(1), s:breakpoints_window.title, "First line should be name", a:test) - - exe 'close' -endfunction - - -function! s:Tests.breakpoint.test_should_open_window_and_show_breakpoints(test) - let filename = s:Mock.mock_file() - " Replace all windows separators (\) and POSIX separators (/) to [\/] for - " making it cross-platform - let file_pattern = substitute(filename, '[\/\\]', '[\\\/\\\\]', "g") - " Write 2 lines of text and set 2 breakpoints (on every line) - exe "normal iblablabla" - exe "normal oblabla" - exe "normal gg" - exe "write" - call g:RubyDebugger.toggle_breakpoint() - exe "normal j" - call g:RubyDebugger.toggle_breakpoint() - - call s:Mock.unmock_file(filename) - - " Lets suggest that some breakpoint is assigned - let g:RubyDebugger.breakpoints[1].debugger_id = 4 - - call g:RubyDebugger.open_breakpoints() - call g:TU.match(getline(2), '1 ' . file_pattern . ':1', "Should show first breakpoint", a:test) - call g:TU.match(getline(3), '2 4 ' . file_pattern . ':2', "Should show second breakpoint", a:test) - - exe 'close' -endfunction - - -function! s:Tests.breakpoint.test_should_open_selected_breakpoint_from_breakpoints_window(test) - let filename = s:Mock.mock_file() - let file_pattern = substitute(filename, '[\/\\]', '[\\\/\\\\]', "g") - exe "normal iblablabla" - exe "normal oblabla" - call g:RubyDebugger.toggle_breakpoint() - exe "normal gg" - exe "write" - exe "wincmd w" - exe "new" - - call g:TU.ok(expand("%") != filename, "It should not be within the file with breakpoint", a:test) - call g:RubyDebugger.open_breakpoints() - exe 'normal 2G' - call s:window_breakpoints_activate_node() - call g:TU.match(expand("%"), file_pattern, "It should open file with breakpoint", a:test) - call g:TU.equal(2, line("."), "It should jump to line with breakpoint", a:test) - call g:RubyDebugger.open_breakpoints() - - call s:Mock.unmock_file(filename) -endfunction - - -function! s:Tests.breakpoint.test_should_delete_breakpoint_from_breakpoints_window(test) - let filename = s:Mock.mock_file() - call g:RubyDebugger.toggle_breakpoint() - call s:Mock.unmock_file(filename) - call g:TU.ok(!empty(g:RubyDebugger.breakpoints), "Breakpoint should be set", a:test) - - call g:RubyDebugger.open_breakpoints() - exe 'normal 2G' - call s:window_breakpoints_delete_node() - call g:TU.equal('', getline(2), "Breakpoint should not be shown", a:test) - call g:TU.ok(empty(g:RubyDebugger.breakpoints), "Breakpoint should be destroyed", a:test) - - exe 'close' -endfunction - - diff --git a/vim/bundle/vim-ruby-debugger/src/tests/command.vim b/vim/bundle/vim-ruby-debugger/src/tests/command.vim deleted file mode 100644 index e157c54..0000000 --- a/vim/bundle/vim-ruby-debugger/src/tests/command.vim +++ /dev/null @@ -1,18 +0,0 @@ -let s:Tests.command = {} - -function! s:Tests.command.before_all() - call s:Mock.mock_debugger() -endfunction - - -function! s:Tests.command.after_all() - call s:Mock.unmock_debugger() -endfunction - - -function! s:Tests.command.test_some_user_command(test) - call g:RubyDebugger.send_command("p \"all users\"") - call g:TU.equal(1, s:Mock.evals, "It should return eval command", a:test) -endfunction - - diff --git a/vim/bundle/vim-ruby-debugger/src/tests/exceptions.vim b/vim/bundle/vim-ruby-debugger/src/tests/exceptions.vim deleted file mode 100644 index 4657055..0000000 --- a/vim/bundle/vim-ruby-debugger/src/tests/exceptions.vim +++ /dev/null @@ -1,49 +0,0 @@ -let s:Tests.exceptions = {} - -function! s:Tests.exceptions.before_all() - call s:Mock.mock_debugger() -endfunction - - -function! s:Tests.exceptions.after_all() - call s:Mock.unmock_debugger() -endfunction - - -function! s:Tests.exceptions.before() - let s:Breakpoint.id = 0 - let g:RubyDebugger.frames = [] - let g:RubyDebugger.exceptions = [] - let g:RubyDebugger.variables = {} - call g:RubyDebugger.queue.empty() - call s:Server._stop_server(s:rdebug_port) - call s:Server._stop_server(s:debugger_port) -endfunction - - -function! s:Tests.exceptions.test_should_not_set_exception_catcher_if_debugger_is_not_running(test) - call g:RubyDebugger.catch_exception("NameError") - call g:TU.equal(0, len(g:RubyDebugger.exceptions), "Exception catcher should not be set", a:test) -endfunction - - -function! s:Tests.exceptions.test_should_clear_exceptions_after_restarting_debugger(test) - exe "Rdebugger" - call g:RubyDebugger.catch_exception("NameError") - call g:TU.equal(1, len(g:RubyDebugger.exceptions), "Exception should be set after starting the server", a:test) - exe "Rdebugger" - call g:TU.equal(0, len(g:RubyDebugger.exceptions), "Exception should be cleared after restarting the server", a:test) -endfunction - - -function! s:Tests.exceptions.test_should_display_exceptions_in_window_breakpoints(test) - exe "Rdebugger" - call g:RubyDebugger.catch_exception("NameError") - call g:RubyDebugger.catch_exception("ArgumentError") - call g:RubyDebugger.open_breakpoints() - call g:TU.match('Exception breakpoints: NameError, ArgumentError', getline(3), "Should show exception breakpoints", a:test) - exe 'close' -endfunction - - - diff --git a/vim/bundle/vim-ruby-debugger/src/tests/frames.vim b/vim/bundle/vim-ruby-debugger/src/tests/frames.vim deleted file mode 100644 index 0601341..0000000 --- a/vim/bundle/vim-ruby-debugger/src/tests/frames.vim +++ /dev/null @@ -1,85 +0,0 @@ -let s:Tests.frames = {} - -function! s:Tests.frames.before_all() - call s:Mock.mock_debugger() -endfunction - - -function! s:Tests.frames.after_all() - call s:Mock.unmock_debugger() -endfunction - - -function! s:Tests.frames.before() - let s:Breakpoint.id = 0 - let g:RubyDebugger.frames = [] - let g:RubyDebugger.variables = {} - call g:RubyDebugger.queue.empty() - call s:Server._stop_server(s:rdebug_port) - call s:Server._stop_server(s:debugger_port) -endfunction - - -function! s:Tests.frames.test_should_display_frames_in_window_frames(test) - let filename = s:Mock.mock_file() - " Replace all windows separators (\) and POSIX separators (/) to [\/] for - " making it cross-platform - let file_pattern = substitute(filename, '[\/\\]', '[\\\/\\\\]', "g") - let s:Mock.file = filename - call g:RubyDebugger.send_command('where') - - call g:RubyDebugger.open_frames() - call g:TU.match(getline(2), '1 Current ' . file_pattern . ':2', "Should show first frame", a:test) - call g:TU.match(getline(3), '2 ' . file_pattern . ':3', "Should show second frame", a:test) - - exe 'close' -endfunction - - -function! s:Tests.frames.test_should_open_file_with_frame(test) - let filename = s:Mock.mock_file() - let file_pattern = substitute(filename, '[\/\\]', '[\\\/\\\\]', "g") - let s:Mock.file = filename - " Write 3 lines of text and set 3 frames (on every line) - exe "normal iblablabla" - exe "normal oblabla" - exe "normal obla" - exe "normal gg" - exe "write" - exe "wincmd w" - call g:TU.ok(expand("%") != filename, "It should not be within the file with frame", a:test) - - call g:RubyDebugger.send_command('where') - call g:TU.equal(2, len(g:RubyDebugger.frames), "2 frames should be set", a:test) - - call g:RubyDebugger.open_frames() - exe 'normal 3G' - call s:window_frames_activate_node() - call g:TU.match(expand("%"), file_pattern, "It should open file with frame", a:test) - call g:TU.equal(3, line("."), "It should jump to line with frame", a:test) - call g:RubyDebugger.open_frames() - - call s:Mock.unmock_file(filename) -endfunction - - -function! s:Tests.frames.test_should_clear_frames_after_movement_command(test) - let g:RubyDebugger.frames = [{ 'bla' : 'bla' }] - call g:RubyDebugger.next() - call g:TU.equal([], g:RubyDebugger.frames, "Frames should be cleaned", a:test) - - let g:RubyDebugger.frames = [{ 'bla' : 'bla' }] - call g:RubyDebugger.step() - call g:TU.equal([], g:RubyDebugger.frames, "Frames should be cleaned", a:test) - - let g:RubyDebugger.frames = [{ 'bla' : 'bla' }] - call g:RubyDebugger.continue() - call g:TU.equal([], g:RubyDebugger.frames, "Frames should be cleaned", a:test) - - let g:RubyDebugger.frames = [{ 'bla' : 'bla' }] - call g:RubyDebugger.exit() - call g:TU.equal([], g:RubyDebugger.frames, "Frames should be cleaned", a:test) -endfunction - - - diff --git a/vim/bundle/vim-ruby-debugger/src/tests/framework.vim b/vim/bundle/vim-ruby-debugger/src/tests/framework.vim deleted file mode 100644 index 98e0456..0000000 --- a/vim/bundle/vim-ruby-debugger/src/tests/framework.vim +++ /dev/null @@ -1,125 +0,0 @@ -let TU = { 'output': '', 'errors': '', 'success': ''} - - -function! TU.run(...) - call g:TU.init() - for key in keys(s:Tests) - " Run tests only if function was called without arguments, of argument == - " current tests group. - if !a:0 || a:1 == key - let g:TU.output = g:TU.output . "\n" . key . ":\n" - if has_key(s:Tests[key], 'before_all') - call s:Tests[key].before_all() - endif - for test in keys(s:Tests[key]) - if test =~ '^test_' - if has_key(s:Tests[key], 'before') - call s:Tests[key].before() - endif - call s:Tests[key][test](test) - if has_key(s:Tests[key], 'after') - call s:Tests[key].after() - endif - endif - endfor - if has_key(s:Tests[key], 'after_all') - call s:Tests[key].after_all() - endif - let g:TU.output = g:TU.output . "\n" - endif - endfor - - call g:TU.show_output() - call g:TU.restore() -endfunction - - -function! TU.init() - let g:TU.breakpoint_id = s:Breakpoint.id - let s:Breakpoint.id = 0 - - let g:TU.variables = g:RubyDebugger.variables - let g:RubyDebugger.variables = {} - - let g:TU.breakpoints = g:RubyDebugger.breakpoints - let g:RubyDebugger.breakpoints = [] - - let g:TU.var_id = s:Var.id - let s:Var.id = 0 - - let s:Mock.breakpoints = 0 - let s:Mock.evals = 0 - - if s:variables_window.is_open() - call s:variables_window.close() - endif - if s:breakpoints_window.is_open() - call s:breakpoints_window.close() - endif - - let g:TU.output = "" - let g:TU.success = "" - let g:TU.errors = "" - - " For correct closing and deleting test files - let g:TU.hidden = &hidden - set nohidden -endfunction - - -function! TU.restore() - let s:Breakpoint.id = g:TU.breakpoint_id - unlet g:TU.breakpoint_id - - let g:RubyDebugger.variables = g:TU.variables - unlet g:TU.variables - - let g:RubyDebugger.breakpoints = g:TU.breakpoints - unlet g:TU.breakpoints - - let s:Var.id = g:TU.var_id - unlet g:TU.var_id - - let &hidden = g:TU.hidden -endfunction - - -function! TU.show_output() - echo g:TU.output . "\n" . g:TU.errors -endfunction - - -function! TU.ok(condition, description, test) - if a:condition - let g:TU.output = g:TU.output . "." - let g:TU.success = g:TU.success . a:test . ": " . a:description . ", true\n" - else - let g:TU.output = g:TU.output . "F" - let g:TU.errors = g:TU.errors . a:test . ": " . a:description . ", expected true, got false.\n" - endif -endfunction - - -function! TU.equal(expected, actual, description, test) - if a:expected == a:actual - let g:TU.output = g:TU.output . "." - let g:TU.success = g:TU.success . a:test . ": " . a:description . ", equals\n" - else - let g:TU.output = g:TU.output . "F" - let g:TU.errors = g:TU.errors . a:test . ": " . a:description . ", expected " . a:expected . ", got " . a:actual . ".\n" - endif -endfunction - - -function! TU.match(expected, actual, description, test) - if a:expected =~ a:actual - let g:TU.output = g:TU.output . "." - let g:TU.success = g:TU.success . a:test . ": " . a:description . ", match one to other\n" - else - let g:TU.output = g:TU.output . "F" - let g:TU.errors = g:TU.errors . a:test . ": " . a:description . ", expected to match " . a:expected . ", got " . a:actual . ".\n" - endif -endfunction - - -let s:Tests = {} diff --git a/vim/bundle/vim-ruby-debugger/src/tests/mock.vim b/vim/bundle/vim-ruby-debugger/src/tests/mock.vim deleted file mode 100644 index e02be85..0000000 --- a/vim/bundle/vim-ruby-debugger/src/tests/mock.vim +++ /dev/null @@ -1,94 +0,0 @@ -let s:Mock = { 'breakpoints': 0, 'evals': 0 } - -function! s:mock_debugger(messages, ...) - let commands = [] - let messages_array = split(a:messages, s:separator) - for message in messages_array - let cmd = "" - if message =~ 'break' - let matches = matchlist(message, 'break \(.*\):\(.*\)') - let cmd = '' - let s:Mock.breakpoints += 1 - elseif message =~ 'delete' - let matches = matchlist(message, 'delete \(.*\)') - let cmd = '' - let s:Mock.breakpoints -= 1 - elseif message =~ 'var local' - let cmd = '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - elseif message =~ 'var instance -0x2418a904' - let cmd = '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - elseif message =~ 'var instance -0x2418a907' - let cmd = '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - elseif message =~ 'var instance -0x2418a906' - let cmd = '' - let cmd = cmd . '' - let cmd = cmd . '' - let cmd = cmd . '' - elseif message =~ 'var instance -0x2418a914' - let cmd = '' - let cmd = cmd . "" - let cmd = cmd . '' - elseif message =~ 'var instance -0x2418a916' - let cmd = '' - let cmd = cmd . "" - let cmd = cmd . '' - elseif message =~ 'where' - let filename = s:Mock.file - let cmd = '' - let cmd = cmd . "" - let cmd = cmd . "" - let cmd = cmd . '' - elseif message =~ '^p ' - let p = matchlist(message, "^p \\(.*\\)")[1] - let s:Mock.evals += 1 - let cmd = '' - endif - if cmd != "" - call add(commands, cmd) - endif - endfor - if !empty(commands) - call writefile([ join(commands, s:separator) ], s:tmp_file) - call g:RubyDebugger.receive_command() - endif -endfunction - - -function! s:Mock.mock_debugger() - let g:RubyDebugger.send_command = function("s:mock_debugger") -endfunction - - -function! s:Mock.unmock_debugger() - let g:RubyDebugger.send_command = function("s:send_message_to_debugger") -endfunction - - -function! s:Mock.mock_file() - let filename = s:runtime_dir . "/tmp/ruby_debugger_test_file" - exe "new " . filename - exe "write" - return filename -endfunction - - -function! s:Mock.unmock_file(filename) - silent exe "close" - call delete(a:filename) -endfunction - - - diff --git a/vim/bundle/vim-ruby-debugger/src/tests/server.vim b/vim/bundle/vim-ruby-debugger/src/tests/server.vim deleted file mode 100644 index 3979853..0000000 --- a/vim/bundle/vim-ruby-debugger/src/tests/server.vim +++ /dev/null @@ -1,48 +0,0 @@ -let s:Tests.server = {} - -function! s:Tests.server.before_all() - let g:RubyDebugger.breakpoints = [] - let g:RubyDebugger.frames = [] - let g:RubyDebugger.variables = {} -endfunction - -function! s:Tests.server.before() - call g:RubyDebugger.queue.empty() - call s:Server._stop_server(s:rdebug_port) - call s:Server._stop_server(s:debugger_port) -endfunction - -function! s:Tests.server.test_should_run_server(test) - exe "Rdebugger" - call g:TU.ok(type(g:RubyDebugger.server) == type({}), "Server should be initialized", a:test) - call g:TU.ok(g:RubyDebugger.server.is_running(), "Server should be run", a:test) - call g:TU.ok(g:RubyDebugger.server.rdebug_pid != "", "Process rdebug-ide should be run", a:test) - call g:TU.ok(g:RubyDebugger.server.debugger_pid != "", "Process debugger.rb should be run", a:test) -endfunction - - -function! s:Tests.server.test_should_stop_server(test) - exe "Rdebugger" - call g:RubyDebugger.server.stop() - call g:TU.ok(!g:RubyDebugger.server.is_running(), "Server should not be run", a:test) - call g:TU.equal("", s:Server._get_pid(s:rdebug_port, 0), "Process rdebug-ide should not exist", a:test) - call g:TU.equal("", s:Server._get_pid(s:debugger_port, 0), "Process debugger.rb should not exist", a:test) - call g:TU.equal("", g:RubyDebugger.server.rdebug_pid, "Pid of rdebug-ide should be nullified", a:test) - call g:TU.equal("", g:RubyDebugger.server.debugger_pid, "Pid of debugger.rb should be nullified", a:test) -endfunction - - -function! s:Tests.server.test_should_kill_old_server_before_starting_new(test) - exe "Rdebugger" - let old_rdebug_pid = g:RubyDebugger.server.rdebug_pid - let old_debugger_pid = g:RubyDebugger.server.debugger_pid - exe "Rdebugger" - call g:TU.ok(g:RubyDebugger.server.is_running(), "Server should be run", a:test) - call g:TU.ok(g:RubyDebugger.server.rdebug_pid != "", "Process rdebug-ide should be run", a:test) - call g:TU.ok(g:RubyDebugger.server.debugger_pid != "", "Process debugger.rb should be run", a:test) - call g:TU.ok(g:RubyDebugger.server.rdebug_pid != old_rdebug_pid, "Rdebug-ide should have new pid", a:test) - call g:TU.ok(g:RubyDebugger.server.debugger_pid != old_debugger_pid, "Debugger.rb should have new pid", a:test) -endfunction - - - diff --git a/vim/bundle/vim-ruby-debugger/src/tests/variables.vim b/vim/bundle/vim-ruby-debugger/src/tests/variables.vim deleted file mode 100644 index 2512a08..0000000 --- a/vim/bundle/vim-ruby-debugger/src/tests/variables.vim +++ /dev/null @@ -1,210 +0,0 @@ -let s:Tests.variables = {} - -function! s:Tests.variables.before_all() - call s:Mock.mock_debugger() -endfunction - - -function! s:Tests.variables.after_all() - call s:Mock.unmock_debugger() -endfunction - - -function! s:Tests.variables.before() - let g:RubyDebugger.breakpoints = [] - let g:RubyDebugger.frames = [] - let g:RubyDebugger.variables = {} - call g:RubyDebugger.queue.empty() - call s:Server._stop_server(s:rdebug_port) - call s:Server._stop_server(s:debugger_port) -endfunction - - -function! s:Tests.variables.test_should_open_window_without_got_variables(test) - call g:RubyDebugger.open_variables() - call g:TU.ok(s:variables_window.is_open(), "Variables window should be opened", a:test) - call g:TU.equal(bufwinnr("%"), s:variables_window.get_number(), "Focus should be into the variables window", a:test) - call g:TU.equal(getline(1), s:variables_window.title, "First line should be name", a:test) - exe 'close' -endfunction - - -" TODO: Now, variables are localized after receiving or -" in ruby_debugger.rb. I don't know how to test them there from here. -"function! s:Tests.variables.test_should_init_variables_after_breakpoint(test) -" let filename = s:Mock.mock_file() -" -" let cmd = '' -" call writefile([ cmd ], s:tmp_file) -" call g:RubyDebugger.receive_command() -" -" call g:TU.equal("VarParent", g:RubyDebugger.variables.type, "Root variable should be initialized", a:test) -" call g:TU.equal(5, len(g:RubyDebugger.variables.children), "4 variables should be initialized", a:test) -" call g:TU.equal(4, len(filter(copy(g:RubyDebugger.variables.children), 'v:val.type == "VarParent"')), "3 Parent variables should be initialized", a:test) -" call g:TU.equal(1, len(filter(copy(g:RubyDebugger.variables.children), 'v:val.type == "VarChild"')), "1 Child variable should be initialized", a:test) -" -" call s:Mock.unmock_file(filename) -"endfunction - - -function! s:Tests.variables.test_should_open_variables_window(test) - call g:RubyDebugger.send_command('var local') - - call g:RubyDebugger.open_variables() - call g:TU.ok(s:variables_window.is_open(), "Variables window should opened", a:test) - call g:TU.equal(bufwinnr("%"), s:variables_window.get_number(), "Focus should be into the variables window", a:test) - call g:TU.equal(getline(1), s:variables_window.title, "First line should be name", a:test) - call g:TU.match(getline(2), '|+self', "Second line should be 'self' variable", a:test) - call g:TU.match(getline(3), '|-some_local', "Third line should be a local variable", a:test) - call g:TU.match(getline(4), '|+array', "4-th line should be an array", a:test) - call g:TU.match(getline(5), '|+quoted_hash', "5-th line should be a hash", a:test) - call g:TU.match(getline(6), '`+hash', "6-th line should be a hash", a:test) - - exe 'close' -endfunction - - -function! s:Tests.variables.test_should_close_variables_window_after_opening(test) - call g:RubyDebugger.send_command('var local') - - call g:RubyDebugger.open_variables() - call g:RubyDebugger.open_variables() - call g:TU.ok(!s:variables_window.is_open(), "Variables window should be closed", a:test) -endfunction - - -function! s:Tests.variables.test_should_open_instance_subvariable(test) - call g:RubyDebugger.send_command('var local') - call g:RubyDebugger.open_variables() - exe 'normal 2G' - - call s:window_variables_activate_node() - call g:TU.ok(s:variables_window.is_open(), "Variables window should opened", a:test) - call g:TU.match(getline(2), '|\~self', "Second line should be opened 'self' variable", a:test) - call g:TU.match(getline(3), '| |+self_array', "Third line should be closed array subvariable", a:test) - call g:TU.match(getline(4), '| |-self_local', "4-th line should be local subvariable", a:test) - call g:TU.match(getline(5), '| `+array', "5-th line should be array", a:test) - call g:TU.match(getline(6), '|-some_local', "6-th line should be local variable", a:test) - - exe 'close' -endfunction - - -function! s:Tests.variables.test_should_open_instance_subvariable_with_quotes(test) - call g:RubyDebugger.send_command('var local') - call g:RubyDebugger.open_variables() - exe 'normal 5G' - - call s:window_variables_activate_node() - call g:TU.ok(s:variables_window.is_open(), "Variables window should opened", a:test) - call g:TU.match(getline(5), '|\~quoted_hash', "5-th line should be hash variable", a:test) - call g:TU.match(getline(6), "| `-'quoted'", "6-th line should be quoted variable", a:test) - - exe 'close' -endfunction - - -function! s:Tests.variables.test_should_close_instance_subvariable(test) - call g:RubyDebugger.send_command('var local') - call g:RubyDebugger.open_variables() - exe 'normal 2G' - - call s:window_variables_activate_node() - call s:window_variables_activate_node() - call g:TU.ok(s:variables_window.is_open(), "Variables window should opened", a:test) - call g:TU.match(getline(2), '|+self', "Second line should be closed 'self' variable", a:test) - - exe 'close' -endfunction - - -function! s:Tests.variables.test_should_open_last_variable_in_list(test) - call g:RubyDebugger.send_command('var local') - call g:RubyDebugger.open_variables() - exe 'normal 6G' - - call s:window_variables_activate_node() - call g:TU.match(getline(6), '`\~hash', "5-th line should be opened hash", a:test) - call g:TU.match(getline(7), ' |-hash_local', "6 line should be local subvariable", a:test) - call g:TU.match(getline(8), ' `+hash_array', "7-th line should be array subvariable", a:test) - - exe 'close' -endfunction - - -function! s:Tests.variables.test_should_open_childs_of_array(test) - call g:RubyDebugger.send_command('var local') - call g:RubyDebugger.open_variables() - exe 'normal 4G' - call s:window_variables_activate_node() - call g:TU.match(getline(4), '|\~array', '4-th line should be opened array', a:test) - call g:TU.match(getline(5), '| |-\[0\]', '5 line should be local subvariable', a:test) - call g:TU.match(getline(6), '| `+\[1\]', '6-th line should be array subvariable', a:test) - - exe 'close' -endfunction - - -function! s:Tests.variables.test_should_clear_variables_after_movement_command(test) - let g:RubyDebugger.variables = { 'bla' : 'bla' } - call g:RubyDebugger.next() - call g:TU.equal({}, g:RubyDebugger.variables, "Variables should be cleaned", a:test) - - let g:RubyDebugger.variables = { 'bla' : 'bla' } - call g:RubyDebugger.step() - call g:TU.equal({}, g:RubyDebugger.variables, "Variables should be cleaned", a:test) - - let g:RubyDebugger.variables = { 'bla' : 'bla' } - call g:RubyDebugger.continue() - call g:TU.equal({}, g:RubyDebugger.variables, "Variables should be cleaned", a:test) - - let g:RubyDebugger.variables = { 'bla' : 'bla' } - call g:RubyDebugger.exit() - call g:TU.equal({}, g:RubyDebugger.variables, "Variables should be cleaned", a:test) -endfunction - - -function! s:Tests.variables.test_should_open_correct_variable_if_variable_has_repeated_name(test) - call g:RubyDebugger.send_command('var local') - call g:RubyDebugger.open_variables() - exe 'normal 2G' - call s:window_variables_activate_node() - exe 'normal 7G' - call s:window_variables_activate_node() - - call g:TU.match(getline(5), '| `+array', "5-th line should be closed array", a:test) - call g:TU.match(getline(6), '|-some_local', "6-th line should be local variable", a:test) - call g:TU.match(getline(7), '|\~array', '7-th line should be opened array', a:test) - call g:TU.match(getline(8), '| |-\[0\]', '8 line should be local subvariable', a:test) - call g:TU.match(getline(9), '| `+\[1\]', '9-th line should be array subvariable', a:test) - - exe 'close' -endfunction - -" Test for issue #6 -"function! s:Tests.variables.test_should_update_opened_variables_on_next_suspend(test) -" call g:RubyDebugger.send_command('var local') -" call g:RubyDebugger.open_variables() -" exe 'normal 2G' -" call s:window_variables_activate_node() -" exe 'normal 7G' -" call s:window_variables_activate_node() -" call g:RubyDebugger.next() -" call g:RubyDebugger.open_variables() -" call g:RubyDebugger.open_variables() -" -" call g:TU.equal(7, line("."), "Current line should = 7", a:test) -" call g:TU.match(getline(2), '|\~self', "Second line should be opened 'self' variable", a:test) -" call g:TU.match(getline(3), '| |+self_array', "Third line should be closed array subvariable", a:test) -" call g:TU.match(getline(4), '| |-self_updated', "4-th line should be local subvariable", a:test) -" call g:TU.match(getline(5), '| `+array', "5-th line should be closed array", a:test) -" call g:TU.match(getline(6), '|-some_local', "6-th line should be local variable", a:test) -" call g:TU.match(getline(7), '|\~array', '7-th line should be opened array', a:test) -" call g:TU.match(getline(8), '| `+\[0\]', '9-th line should be array subvariable', a:test) -" call g:TU.match(getline(9), '|+quoted_hash', '9-th line should be array subvariable', a:test) -" -" call g:RubyDebugger.open_variables() -" unlet s:Mock.next -" call s:Mock.unmock_file(s:Mock.file) -" -"endfunction diff --git a/vim/bundle/vim-rvm/.gitignore b/vim/bundle/vim-rvm/.gitignore new file mode 100644 index 0000000..0a56e3f --- /dev/null +++ b/vim/bundle/vim-rvm/.gitignore @@ -0,0 +1 @@ +/doc/tags diff --git a/vim/bundle/vim-rvm/README.markdown b/vim/bundle/vim-rvm/README.markdown new file mode 100644 index 0000000..ecf7007 --- /dev/null +++ b/vim/bundle/vim-rvm/README.markdown @@ -0,0 +1,74 @@ +rvm.vim +======= + +Want to use [RVM](http://rvm.beginrescueend.com) with Vim? You don't +need a plugin to do that: Just start Vim from your RVM enabled shell +and it will work. But say you started MacVim from Launchpad, or you +started Vim with one version of Ruby and now you want another. That's +where rvm.vim comes in. + + :Rvm 1.9.2 + +If you want to see the version that was chosen, use `use`: + + :Rvm use default + +If you leave off the version, it goes `.rvmrc` hunting relative to the +current buffer. + + :Rvm + :Rvm use + +If you really want to get crazy, you can make this happen automatically +as you switch from buffer to buffer. + + :autocmd BufEnter * Rvm + +You can also invoke any old `rvm` command. + + :Rvm install 1.9.3 + +Add `%{rvm#statusline()}` to `'statusline'` (or `'titlestring'`) to see +the current Ruby version at all times. + +Installation +------------ + +If you don't have a preferred installation method, I recommend +installing [pathogen.vim](https://github.com/tpope/vim-pathogen), and +then simply copy and paste: + + cd ~/.vim/bundle + git clone git://github.com/tpope/vim-rvm.git + +Once help tags have been generated, you can view the manual with +`:help rvm`. + +FAQ +--- + +> RVM doesn't work in my Vim. + +You're using zsh on OS X, aren't you? Move that stupid `/etc/zshenv` +to `/etc/zshrc`. + +Contributing +------------ + +See the contribution guidelines for +[rails.vim](https://github.com/tpope/vim-rails#readme). + +Self-Promotion +-------------- + +Like rvm.vim? Follow the repository on +[GitHub](https://github.com/tpope/vim-rvm). And if +you're feeling especially charitable, follow [tpope](http://tpo.pe/) on +[Twitter](http://twitter.com/tpope) and +[GitHub](https://github.com/tpope). + +License +------- + +Copyright (c) Tim Pope. Distributed under the same terms as Vim itself. +See `:help license`. diff --git a/vim/bundle/vim-rvm/doc/rvm.txt b/vim/bundle/vim-rvm/doc/rvm.txt new file mode 100644 index 0000000..e94b431 --- /dev/null +++ b/vim/bundle/vim-rvm/doc/rvm.txt @@ -0,0 +1,35 @@ +*rvm.txt* Switch Ruby versions from inside Vim + +Author: Tim Pope +License: Same terms as Vim itself (see |license|) + +This plugin is only available if 'compatible' is not set. + +COMMANDS *:Rvm* + +:Rvm Set the current Ruby version to the version found in + the .rvmrc for the current buffer. If no .rvmrc is + found, set it to the default version. + +:Rvm {version} Set the current Ruby version to {version}. + +:Rvm use [version] As above, but echo the version chosen. + +:Rvm {command} Run rvm with arbitrary arguments. + +To automatically switch Ruby versions when switching buffers: +> + autocmd BufEnter * Rvm + +STATUSLINE *rvm#statusline()* + +Add rvm#statusline() to 'statusline' (or 'titlestring') to see the current +version in your statusline (or title bar). + +ABOUT *rvm-about* + +Grab the latest version or report a bug on GitHub: + +https://github.com/tpope/vim-rvm + + vim:tw=78:et:ft=help:norl: diff --git a/vim/bundle/vim-rvm/plugin/rvm.vim b/vim/bundle/vim-rvm/plugin/rvm.vim new file mode 100644 index 0000000..2c34e4b --- /dev/null +++ b/vim/bundle/vim-rvm/plugin/rvm.vim @@ -0,0 +1,156 @@ +" rvm.vim - Switch Ruby versions from inside Vim +" Maintainer: Tim Pope + +if exists('g:loaded_rvm') || v:version < 700 || &cp + finish +endif + +if !exists('$rvm_path') && isdirectory(expand('~/.rvm')) + let $rvm_path = expand('~/.rvm') + let $PATH .= ':' . $rvm_path . '/bin' +endif + +if !exists('$rvm_path') + finish +endif + +let g:loaded_rvm = 1 + +" Utility {{{1 + +function! s:shellesc(arg) abort + if a:arg =~ '^[A-Za-z0-9_/.-]\+$' + return a:arg + else + return shellescape(a:arg) + endif +endfunction + +" }}}1 +" :Rvm {{{1 + +function! rvm#buffer_path_identifier(...) + let name = bufname(a:0 ? a:1 : '%') + if name ==# '' + let path = '.' + elseif isdirectory(name) + let path = name + else + let path = fnamemodify(name, ':h') + endif + return system('rvm tools path-identifier '.s:shellesc(path)) +endfunction + +function! s:Rvm(bang,...) abort + let path = split($PATH,':') + call filter(path, 'v:val[0:strlen($rvm_path)] !=# $rvm_path."/"') + + if a:0 && a:0 < 3 && a:1 ==# 'use' + let use = 1 + let args = a:000[1:-1] + else + let use = 0 + let args = copy(a:000) + endif + + if len(args) > 1 || (len(args) == 1 && args[0] !~ '^\%(@\|\d\|default\|j\=ruby\|goruby\|rbx\|ree\|kiji\|maglev\|ironruby\|system\)' && !use) + return '!rvm '.join(map(copy(a:000), 's:shellesc(v:val)'), ' ') + elseif !empty(args) && args[-1] ==# 'system' + let desired = 'system' + elseif !empty(args) + let desired = system('rvm tools strings '.s:shellesc(args[0]))[0:-2] + elseif use || !exists('b:rvm_string') + let desired = rvm#buffer_path_identifier() + else + let desired = b:rvm_string + endif + + if desired ==# 'system' + let $RUBY_VERSION = '' + let $MY_RUBY_HOME = '' + let $IRBRC = expand('~/.irbrc') + let $PATH = join(path + [$rvm_path.'/bin'],':') + let $GEM_HOME = system('env -i PATH="'.$PATH.'" ruby -rubygems -e "print Gem.dir"') + let $GEM_PATH = system('env -i PATH="'.$PATH.'" ruby -rubygems -e "print Gem.path.join(%{:})"') + if use + return 'echomsg "Using system ruby"' + else + return '' + endif + endif + + let ver = matchstr(desired,'[^@]*') + let gemset = matchstr(desired,'@.*') + if ver ==# '' + return 'echoerr "Ruby version not found"' + endif + if !isdirectory($rvm_path . '/rubies/' . ver) + if $rvm_install_on_use_flag + execute 'Rvm install '.ver + else + return 'echoerr "Ruby version not installed: :Rvm install ".'.string(ver) + endif + endif + let b:rvm_string = desired + + let $RUBY_VERSION = ver + let $GEM_HOME = $rvm_path . '/gems/' . $RUBY_VERSION . gemset + let $MY_RUBY_HOME = $rvm_path . '/rubies/' . $RUBY_VERSION + let $IRBRC = $MY_RUBY_HOME . '/.irbrc' + + let gemsets = [$GEM_HOME, $rvm_path . '/gems/' . $RUBY_VERSION . '@global'] + + let $GEM_PATH = join(gemsets, ':') + let $PATH = join( + \ [$MY_RUBY_HOME.'/bin'] + + \ map(gemsets,'v:val."/bin"') + + \ [$rvm_path.'/bin'] + + \ path, ':') + if use + return 'echomsg "Using " . $GEM_HOME' + else + return '' + endif +endfunction + +function! s:Complete(A,L,P) + if a:A =~# '@' + let requested = matchstr(a:A,'^[^@]*') + let desired = system('rvm tools strings '.s:shellesc(requested))[0:-2] + let all = split(glob($rvm_path.'/gems/'.desired.'@*'),"\n") + call map(all,"v:val[strlen($rvm_path)+6:-1]") + call map(all,'substitute(v:val,"^[^@]*",requested,"")') + else + let all = split(glob($rvm_path.'/rubies/*'),"\n") + call map(all,"v:val[strlen($rvm_path)+8:-1]") + if a:A !~# '^r' + call map(all,'substitute(v:val,"^ruby-\\ze\\d","","")') + endif + endif + return join(all,"\n") +endfunction + +command! -bar -nargs=* -complete=custom,s:Complete Rvm :execute s:Rvm(0,) + +" }}}1 +" Statusline {{{1 + +function! rvm#string() + return matchstr($GEM_HOME,'[^/]*$') +endfunction + +function! rvm#statusline() + return substitute('['.rvm#string().']','^\[\]$','','') +endfunction + +function! rvm#statusline_ft_ruby() + if &filetype ==# 'ruby' + return rvm#statusline() + else + return '' + endif +endfunction + +" }}}1 + +" vim:set sw=2 sts=2: diff --git a/vim/update_bundles.rb b/vim/update_bundles.rb index a1f8d8e..8bebab1 100755 --- a/vim/update_bundles.rb +++ b/vim/update_bundles.rb @@ -13,6 +13,7 @@ "https://github.com/tpope/vim-cucumber.git", "https://github.com/tpope/vim-rake.git", "https://github.com/tpope/vim-bundler.git", + "https://github.com/tpope/vim-rvm.git", "https://github.com/scrooloose/nerdcommenter.git", "https://github.com/scrooloose/nerdtree.git", "https://github.com/tpope/vim-abolish.git", @@ -23,7 +24,6 @@ "https://github.com/vim-ruby/vim-ruby.git", "https://github.com/tsaleh/vim-matchit.git", "https://github.com/othree/html5.vim.git", - "https://github.com/astashov/vim-ruby-debugger.git", "https://github.com/nelstrom/vim-textobj-rubyblock.git", "https://github.com/kana/vim-textobj-user.git", "https://github.com/fholgado/minibufexpl.vim.git", @@ -60,7 +60,8 @@ "https://github.com/kchmck/vim-coffee-script.git", #"https://github.com/vim-scripts/perforce.git", "https://github.com/csexton/jekyll.vim.git", - "https://github.com/ervandew/supertab.git" + "https://github.com/ervandew/supertab.git", + "https://github.com/wincent/Command-T.git", ] vim_org_scripts = [ diff --git a/vimrc b/vimrc index 28e25fb..014037d 100644 --- a/vimrc +++ b/vimrc @@ -41,6 +41,7 @@ set updatetime=100 " Set update time to 1/10 second set wildmenu set wildmode=list:longest,full set showbreak=-> +set listchars=tab:▸\ ,eol:¬ set tags=./tags; @@ -214,6 +215,9 @@ nmap ` :QFix map :cn map :cp +" Toggle `set list` +nmap l :set list! + " Taglist nnoremap :TlistToggle @@ -238,6 +242,44 @@ nnoremap :NERDTreeToggle " Gtags mapping map ] :GtagsCursor +" Command-T mappings +cnoremap %% =expand('%:h').'/' +map e :edit %% +map v :view %% +" Open files with f +map f :CommandTFlush\|:CommandT +" Open files, limited to the directory of the current file, with gf +map gf :CommandTFlush\|:CommandT %% + +map gv :CommandTFlush\|:CommandT app/views +map gc :CommandTFlush\|:CommandT app/controllers +map gm :CommandTFlush\|:CommandT app/models +map gh :CommandTFlush\|:CommandT app/helpers +map gl :CommandTFlush\|:CommandT lib +map gp :CommandTFlush\|:CommandT public +map gs :CommandTFlush\|:CommandT public/stylesheets +map gr :topleft :split config/routes.rb +map gg :topleft 100 :split Gemfile + +function! ShowRoutes() + " Requires 'scratch' plugin + :topleft 100 :split __Routes__ + " Make sure Vim doesn't write __Routes__ as a file + :set buftype=nofile + " Delete everything + :normal 1GdG + " Put routes output in buffer + :0r! rake -s routes + " Size window to number of lines (1 plus rake output length) + :exec ":normal " . line("$") . "_ " + " Move cursor to bottom + :normal 1GG + " Delete empty trailing line + :normal dd +endfunction +map gR :call ShowRoutes() + + " Capture the output of a command to a new tab function! Capture (cmd) redir => message @@ -253,7 +295,7 @@ inoremap u inoremap u " AutoComplPop Configuration -let g:acp_enableAtStartup = 1 +let g:acp_enableAtStartup = 0 inoremap pumvisible() \|\| &omnifunc == '' ? \ "\C-n>" :