From 0d23b6e515a01a5782532351821ebfa11f3d6cf2 Mon Sep 17 00:00:00 2001 From: Ben Beltran Date: Mon, 8 Oct 2012 11:44:10 -0500 Subject: Add vim again :) --- vim/tmp/command_t/ruby/command-t/controller.rb | 317 +++++++++++++++++ vim/tmp/command_t/ruby/command-t/depend | 24 ++ vim/tmp/command_t/ruby/command-t/ext.c | 65 ++++ vim/tmp/command_t/ruby/command-t/ext.h | 36 ++ vim/tmp/command_t/ruby/command-t/extconf.rb | 32 ++ vim/tmp/command_t/ruby/command-t/finder.rb | 52 +++ .../ruby/command-t/finder/buffer_finder.rb | 35 ++ .../command_t/ruby/command-t/finder/file_finder.rb | 35 ++ vim/tmp/command_t/ruby/command-t/match.c | 189 ++++++++++ vim/tmp/command_t/ruby/command-t/match.h | 29 ++ vim/tmp/command_t/ruby/command-t/match_window.rb | 387 +++++++++++++++++++++ vim/tmp/command_t/ruby/command-t/matcher.c | 164 +++++++++ vim/tmp/command_t/ruby/command-t/matcher.h | 30 ++ vim/tmp/command_t/ruby/command-t/prompt.rb | 165 +++++++++ vim/tmp/command_t/ruby/command-t/ruby_compat.h | 49 +++ vim/tmp/command_t/ruby/command-t/scanner.rb | 28 ++ .../ruby/command-t/scanner/buffer_scanner.rb | 42 +++ .../ruby/command-t/scanner/file_scanner.rb | 94 +++++ vim/tmp/command_t/ruby/command-t/settings.rb | 77 ++++ vim/tmp/command_t/ruby/command-t/stub.rb | 46 +++ vim/tmp/command_t/ruby/command-t/vim.rb | 43 +++ .../command_t/ruby/command-t/vim/path_utilities.rb | 40 +++ vim/tmp/command_t/ruby/command-t/vim/screen.rb | 32 ++ vim/tmp/command_t/ruby/command-t/vim/window.rb | 38 ++ 24 files changed, 2049 insertions(+) create mode 100644 vim/tmp/command_t/ruby/command-t/controller.rb create mode 100644 vim/tmp/command_t/ruby/command-t/depend create mode 100644 vim/tmp/command_t/ruby/command-t/ext.c create mode 100644 vim/tmp/command_t/ruby/command-t/ext.h create mode 100644 vim/tmp/command_t/ruby/command-t/extconf.rb create mode 100644 vim/tmp/command_t/ruby/command-t/finder.rb create mode 100644 vim/tmp/command_t/ruby/command-t/finder/buffer_finder.rb create mode 100644 vim/tmp/command_t/ruby/command-t/finder/file_finder.rb create mode 100644 vim/tmp/command_t/ruby/command-t/match.c create mode 100644 vim/tmp/command_t/ruby/command-t/match.h create mode 100644 vim/tmp/command_t/ruby/command-t/match_window.rb create mode 100644 vim/tmp/command_t/ruby/command-t/matcher.c create mode 100644 vim/tmp/command_t/ruby/command-t/matcher.h create mode 100644 vim/tmp/command_t/ruby/command-t/prompt.rb create mode 100644 vim/tmp/command_t/ruby/command-t/ruby_compat.h create mode 100644 vim/tmp/command_t/ruby/command-t/scanner.rb create mode 100644 vim/tmp/command_t/ruby/command-t/scanner/buffer_scanner.rb create mode 100644 vim/tmp/command_t/ruby/command-t/scanner/file_scanner.rb create mode 100644 vim/tmp/command_t/ruby/command-t/settings.rb create mode 100644 vim/tmp/command_t/ruby/command-t/stub.rb create mode 100644 vim/tmp/command_t/ruby/command-t/vim.rb create mode 100644 vim/tmp/command_t/ruby/command-t/vim/path_utilities.rb create mode 100644 vim/tmp/command_t/ruby/command-t/vim/screen.rb create mode 100644 vim/tmp/command_t/ruby/command-t/vim/window.rb (limited to 'vim/tmp/command_t/ruby/command-t') diff --git a/vim/tmp/command_t/ruby/command-t/controller.rb b/vim/tmp/command_t/ruby/command-t/controller.rb new file mode 100644 index 0000000..29e61b6 --- /dev/null +++ b/vim/tmp/command_t/ruby/command-t/controller.rb @@ -0,0 +1,317 @@ +# 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/finder/buffer_finder' +require 'command-t/finder/file_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 + @buffer_finder = CommandT::BufferFinder.new + set_up_file_finder + set_up_max_height + end + + def show_buffer_finder + @path = VIM::pwd + @active_finder = @buffer_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) + @file_finder.path = @path + @active_finder = @file_finder + 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 flush + set_up_max_height + set_up_file_finder + 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') + @focus = @prompt + @prompt.focus + register_for_key_presses + clear # clears prompt and lists matches + end + + def set_up_max_height + @max_height = get_number('g:CommandTMaxHeight') || 0 + end + + def set_up_file_finder + @file_finder = CommandT::FileFinder.new nil, + :max_files => get_number('g:CommandTMaxFiles'), + :max_depth => get_number('g:CommandTMaxDepth'), + :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 exists? name + ::VIM::evaluate("exists(\"#{name}\")").to_i != 0 + end + + def get_number name + exists?(name) ? ::VIM::evaluate("#{name}").to_i : nil + end + + def get_bool name + exists?(name) ? ::VIM::evaluate("#{name}").to_i != 0 : nil + end + + def get_string name + exists?(name) ? ::VIM::evaluate("#{name}").to_s : nil + end + + # expect a string or a list of strings + def get_list_or_string name + return nil unless exists?(name) + list_or_string = ::VIM::evaluate("#{name}") + if list_or_string.kind_of?(Array) + list_or_string.map { |item| item.to_s } + else + list_or_string.to_s + end + end + + # 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 + ::VIM::command "silent #{command} #{selection}" + end + + def map key, function, param = nil + ::VIM::command "noremap #{key} " \ + ":call CommandT#{function}(#{param})" + end + + def xterm? + !!(::VIM::evaluate('&term') =~ /\Axterm/) + end + + def vt100? + !!(::VIM::evaluate('&term') =~ /\Avt100/) + 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) + { 'Backspace' => '', + 'Delete' => '', + 'AcceptSelection' => '', + 'AcceptSelectionSplit' => ['', ''], + 'AcceptSelectionTab' => '', + 'AcceptSelectionVSplit' => '', + 'ToggleFocus' => '', + 'Cancel' => ['', ''], + 'SelectNext' => ['', '', ''], + 'SelectPrev' => ['', '', ''], + 'Clear' => '', + 'CursorLeft' => ['', ''], + 'CursorRight' => ['', ''], + 'CursorEnd' => '', + 'CursorStart' => '' }.each do |key, value| + if override = get_list_or_string("g:CommandT#{key}Map") + [override].flatten.each do |mapping| + map mapping, key + end + else + [value].flatten.each do |mapping| + map mapping, key unless mapping == '' && (xterm? || vt100?) + 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 + end # class Controller +end # module commandT diff --git a/vim/tmp/command_t/ruby/command-t/depend b/vim/tmp/command_t/ruby/command-t/depend new file mode 100644 index 0000000..bfa9552 --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/ext.c b/vim/tmp/command_t/ruby/command-t/ext.c new file mode 100644 index 0000000..c5026cc --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/ext.h b/vim/tmp/command_t/ruby/command-t/ext.h new file mode 100644 index 0000000..89ff076 --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/extconf.rb b/vim/tmp/command_t/ruby/command-t/extconf.rb new file mode 100644 index 0000000..58503b6 --- /dev/null +++ b/vim/tmp/command_t/ruby/command-t/extconf.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. + +require 'mkmf' + +def missing item + puts "couldn't find #{item} (required)" + exit 1 +end + +have_header('ruby.h') or missing('ruby.h') +create_makefile('ext') diff --git a/vim/tmp/command_t/ruby/command-t/finder.rb b/vim/tmp/command_t/ruby/command-t/finder.rb new file mode 100644 index 0000000..a3d0b09 --- /dev/null +++ b/vim/tmp/command_t/ruby/command-t/finder.rb @@ -0,0 +1,52 @@ +# 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 + +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 + 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 flush + @scanner.flush + end + + def path= path + @scanner.path = path + end + end # class Finder +end # CommandT diff --git a/vim/tmp/command_t/ruby/command-t/finder/buffer_finder.rb b/vim/tmp/command_t/ruby/command-t/finder/buffer_finder.rb new file mode 100644 index 0000000..2319c24 --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/finder/file_finder.rb b/vim/tmp/command_t/ruby/command-t/finder/file_finder.rb new file mode 100644 index 0000000..a9ed231 --- /dev/null +++ b/vim/tmp/command_t/ruby/command-t/finder/file_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/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 + end # class FileFinder +end # CommandT diff --git a/vim/tmp/command_t/ruby/command-t/match.c b/vim/tmp/command_t/ruby/command-t/match.c new file mode 100644 index 0000000..e32fb0b --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/match.h b/vim/tmp/command_t/ruby/command-t/match.h new file mode 100644 index 0000000..c3ce929 --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/match_window.rb b/vim/tmp/command_t/ruby/command-t/match_window.rb new file mode 100644 index 0000000..f984287 --- /dev/null +++ b/vim/tmp/command_t/ruby/command-t/match_window.rb @@ -0,0 +1,387 @@ +# 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 'ostruct' +require 'command-t/settings' + +module CommandT + class MatchWindow + @@selection_marker = '> ' + @@marker_length = @@selection_marker.length + @@unselected_marker = ' ' * @@marker_length + @@buffer = nil + + def initialize options = {} + @prompt = options[:prompt] + @reverse_list = options[:match_window_reverse] + + # save existing window dimensions so we can restore them later + @windows = [] + (0..(::VIM::Window.count - 1)).each do |i| + window = OpenStruct.new :index => i, :height => ::VIM::Window[i].height + @windows << window + 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 } + + # 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 '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 ruby $command_t.leave' + ::VIM::command 'autocmd BufUnload ruby $command_t.unload' + + @has_focus = false + @selection = nil + @abbrev = '' + @window = $curwin + end + + def close + # 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 'bwipeout! GoToFile' + @@buffer = nil + else + ::VIM::command "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 = 1 + @@buffer[1] = "-- #{msg} --" + lock + end + + def restore_window_dimensions + # sort from tallest to shortest + @windows.sort! { |a, b| b.height <=> a.height } + + # 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 + window = ::VIM::Window[w.index] + window.height = w.height if window + end + end + + def match_text_for_idx idx + match = truncated_match @matches[idx] + if idx == @selection + prefix = @@selection_marker + suffix = padding_for_selected_match match + else + prefix = @@unselected_marker + suffix = '' + end + prefix + match + suffix + 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 > max_lines ? max_lines : match_count + @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 + # as :highlight returns nothing and only prints, + # must redirect its output to a variable + ::VIM::command 'silent redir => g:command_t_cursor_highlight' + + # force 0 verbosity to ensure origin information isn't printed as well + ::VIM::command 'silent! 0verbose highlight Cursor' + ::VIM::command 'silent redir END' + + # 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::evaluate 'g:command_t_cursor_highlight' + 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/tmp/command_t/ruby/command-t/matcher.c b/vim/tmp/command_t/ruby/command-t/matcher.c new file mode 100644 index 0000000..7cd8a3e --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/matcher.h b/vim/tmp/command_t/ruby/command-t/matcher.h new file mode 100644 index 0000000..6207e37 --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/prompt.rb b/vim/tmp/command_t/ruby/command-t/prompt.rb new file mode 100644 index 0000000..743e873 --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/ruby_compat.h b/vim/tmp/command_t/ruby/command-t/ruby_compat.h new file mode 100644 index 0000000..e7960a2 --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/scanner.rb b/vim/tmp/command_t/ruby/command-t/scanner.rb new file mode 100644 index 0000000..5e5e3c9 --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/scanner/buffer_scanner.rb b/vim/tmp/command_t/ruby/command-t/scanner/buffer_scanner.rb new file mode 100644 index 0000000..aa85497 --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/scanner/file_scanner.rb b/vim/tmp/command_t/ruby/command-t/scanner/file_scanner.rb new file mode 100644 index 0000000..4ea15c8 --- /dev/null +++ b/vim/tmp/command_t/ruby/command-t/scanner/file_scanner.rb @@ -0,0 +1,94 @@ +# 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 + + def initialize path = Dir.pwd, options = {} + @path = path + @max_depth = options[:max_depth] || 15 + @max_files = options[:max_files] || 10_000 + @scan_dot_directories = options[:scan_dot_directories] || false + end + + def paths + return @paths unless @paths.nil? + begin + @paths = [] + @depth = 0 + @files = 0 + @prefix_len = @path.chomp('/').length + add_paths_for_directory @path, @paths + rescue FileLimitExceeded + end + @paths + end + + def flush + @paths = nil + end + + def path= str + if @path != str + @path = str + flush + end + end + + private + + 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/tmp/command_t/ruby/command-t/settings.rb b/vim/tmp/command_t/ruby/command-t/settings.rb new file mode 100644 index 0000000..c15016a --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/stub.rb b/vim/tmp/command_t/ruby/command-t/stub.rb new file mode 100644 index 0000000..6e8b074 --- /dev/null +++ b/vim/tmp/command_t/ruby/command-t/stub.rb @@ -0,0 +1,46 @@ +# 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'] + + def show_file_finder + warn *@@load_error + end + + def flush + 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/tmp/command_t/ruby/command-t/vim.rb b/vim/tmp/command_t/ruby/command-t/vim.rb new file mode 100644 index 0000000..b4e40fc --- /dev/null +++ b/vim/tmp/command_t/ruby/command-t/vim.rb @@ -0,0 +1,43 @@ +# 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 '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.pwd + ::VIM::evaluate 'getcwd()' + 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/tmp/command_t/ruby/command-t/vim/path_utilities.rb b/vim/tmp/command_t/ruby/command-t/vim/path_utilities.rb new file mode 100644 index 0000000..8564300 --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/vim/screen.rb b/vim/tmp/command_t/ruby/command-t/vim/screen.rb new file mode 100644 index 0000000..fb7ba33 --- /dev/null +++ b/vim/tmp/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/tmp/command_t/ruby/command-t/vim/window.rb b/vim/tmp/command_t/ruby/command-t/vim/window.rb new file mode 100644 index 0000000..1e53d56 --- /dev/null +++ b/vim/tmp/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 -- cgit