ignore on .netrwhist
[my-vim-dotfolder.git] / PACKAGES / command-t-0.8.1.vba
blob08bb98bc409e64d3c37e710efbf8d58887a6b47c
1 " Vimball Archiver by Charles E. Campbell, Jr., Ph.D.
2 UseVimball
3 finish
4 ruby/command-t/controller.rb    [[[1
5 289
6 # Copyright 2010 Wincent Colaiuta. All rights reserved.
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions are met:
11 # 1. Redistributions of source code must retain the above copyright notice,
12 #    this list of conditions and the following disclaimer.
13 # 2. Redistributions in binary form must reproduce the above copyright notice,
14 #    this list of conditions and the following disclaimer in the documentation
15 #    and/or other materials provided with the distribution.
17 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
21 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
29 require 'command-t/finder'
30 require 'command-t/match_window'
31 require 'command-t/prompt'
33 module CommandT
34   class Controller
35     def initialize
36       @prompt = Prompt.new
37       set_up_max_height
38       set_up_finder
39     end
41     def show
42       # optional parameter will be desired starting directory, or ""
43       @path           = File.expand_path(::VIM::evaluate('a:arg'), VIM::pwd)
44       @finder.path    = @path
45       @initial_window = $curwin
46       @initial_buffer = $curbuf
47       @match_window   = MatchWindow.new \
48         :prompt               => @prompt,
49         :match_window_at_top  => get_bool('g:CommandTMatchWindowAtTop')
50       @focus          = @prompt
51       @prompt.focus
52       register_for_key_presses
53       clear # clears prompt and list matches
54     rescue Errno::ENOENT
55       # probably a problem with the optional parameter
56       @match_window.print_no_such_file_or_directory
57     end
59     def hide
60       @match_window.close
61       if VIM::Window.select @initial_window
62         ::VIM::command "silent b #{@initial_buffer.number}"
63       end
64     end
66     def flush
67       set_up_max_height
68       set_up_finder
69     end
71     def handle_key
72       key = ::VIM::evaluate('a:arg').to_i.chr
73       if @focus == @prompt
74         @prompt.add! key
75         list_matches
76       else
77         @match_window.find key
78       end
79     end
81     def backspace
82       if @focus == @prompt
83         @prompt.backspace!
84         list_matches
85       end
86     end
88     def delete
89       if @focus == @prompt
90         @prompt.delete!
91         list_matches
92       end
93     end
95     def accept_selection options = {}
96       selection = @match_window.selection
97       hide
98       open_selection(selection, options) unless selection.nil?
99     end
101     def toggle_focus
102       @focus.unfocus # old focus
103       if @focus == @prompt
104         @focus = @match_window
105       else
106         @focus = @prompt
107       end
108       @focus.focus # new focus
109     end
111     def cancel
112       hide
113     end
115     def select_next
116       @match_window.select_next
117     end
119     def select_prev
120       @match_window.select_prev
121     end
123     def clear
124       @prompt.clear!
125       list_matches
126     end
128     def cursor_left
129       @prompt.cursor_left if @focus == @prompt
130     end
132     def cursor_right
133       @prompt.cursor_right if @focus == @prompt
134     end
136     def cursor_end
137       @prompt.cursor_end if @focus == @prompt
138     end
140     def cursor_start
141       @prompt.cursor_start if @focus == @prompt
142     end
144   private
146     def set_up_max_height
147       @max_height = get_number('g:CommandTMaxHeight') || 0
148     end
150     def set_up_finder
151       @finder = CommandT::Finder.new nil,
152         :max_files              => get_number('g:CommandTMaxFiles'),
153         :max_depth              => get_number('g:CommandTMaxDepth'),
154         :always_show_dot_files  => get_bool('g:CommandTAlwaysShowDotFiles'),
155         :never_show_dot_files   => get_bool('g:CommandTNeverShowDotFiles'),
156         :scan_dot_directories   => get_bool('g:CommandTScanDotDirectories')
157     end
159     def exists? name
160       ::VIM::evaluate("exists(\"#{name}\")").to_i != 0
161     end
163     def get_number name
164       exists?(name) ? ::VIM::evaluate("#{name}").to_i : nil
165     end
167     def get_bool name
168       exists?(name) ? ::VIM::evaluate("#{name}").to_i != 0 : nil
169     end
171     def get_string name
172       exists?(name) ? ::VIM::evaluate("#{name}").to_s : nil
173     end
175     # expect a string or a list of strings
176     def get_list_or_string name
177       return nil unless exists?(name)
178       list_or_string = ::VIM::evaluate("#{name}")
179       if list_or_string.kind_of?(Array)
180         list_or_string.map { |item| item.to_s }
181       else
182         list_or_string.to_s
183       end
184     end
186     # Backslash-escape space, \, |, %, #, "
187     def sanitize_path_string str
188       # for details on escaping command-line mode arguments see: :h :
189       # (that is, help on ":") in the Vim documentation.
190       str.gsub(/[ \\|%#"]/, '\\\\\0')
191     end
193     def default_open_command
194       if !get_bool('&hidden') && get_bool('&modified')
195         'sp'
196       else
197         'e'
198       end
199     end
201     def ensure_appropriate_window_selection
202       # normally we try to open the selection in the current window, but there
203       # is one exception:
204       #
205       # - we don't touch any "unlisted" buffer with buftype "nofile" (such as
206       #   NERDTree or MiniBufExplorer); this is to avoid things like the "Not
207       #   enough room" error which occurs when trying to open in a split in a
208       #   shallow (potentially 1-line) buffer like MiniBufExplorer is current
209       #
210       # Other "unlisted" buffers, such as those with buftype "help" are treated
211       # normally.
212       initial = $curwin
213       while true do
214         break unless ::VIM::evaluate('&buflisted').to_i == 0 &&
215           ::VIM::evaluate('&buftype').to_s == 'nofile'
216         ::VIM::command 'wincmd w'     # try next window
217         break if $curwin == initial # have already tried all
218       end
219     end
221     def open_selection selection, options = {}
222       command = options[:command] || default_open_command
223       selection = File.expand_path selection, @path
224       selection = sanitize_path_string selection
225       ensure_appropriate_window_selection
226       ::VIM::command "silent #{command} #{selection}"
227     end
229     def map key, function, param = nil
230       ::VIM::command "noremap <silent> <buffer> #{key} " \
231         ":call CommandT#{function}(#{param})<CR>"
232     end
234     def xterm?
235       !!(::VIM::evaluate('&term') =~ /\Axterm/)
236     end
238     def vt100?
239       !!(::VIM::evaluate('&term') =~ /\Avt100/)
240     end
242     def register_for_key_presses
243       # "normal" keys (interpreted literally)
244       numbers     = ('0'..'9').to_a.join
245       lowercase   = ('a'..'z').to_a.join
246       uppercase   = lowercase.upcase
247       punctuation = '<>`@#~!"$%&/()=+*-_.,;:?\\\'{}[] ' # and space
248       (numbers + lowercase + uppercase + punctuation).each_byte do |b|
249         map "<Char-#{b}>", 'HandleKey', b
250       end
252       # "special" keys (overridable by settings)
253       { 'Backspace'             => '<BS>',
254         'Delete'                => '<Del>',
255         'AcceptSelection'       => '<CR>',
256         'AcceptSelectionSplit'  => ['<C-CR>', '<C-s>'],
257         'AcceptSelectionTab'    => '<C-t>',
258         'AcceptSelectionVSplit' => '<C-v>',
259         'ToggleFocus'           => '<Tab>',
260         'Cancel'                => ['<C-c>', '<Esc>'],
261         'SelectNext'            => ['<C-n>', '<C-j>', '<Down>'],
262         'SelectPrev'            => ['<C-p>', '<C-k>', '<Up>'],
263         'Clear'                 => '<C-u>',
264         'CursorLeft'            => ['<Left>', '<C-h>'],
265         'CursorRight'           => ['<Right>', '<C-l>'],
266         'CursorEnd'             => '<C-e>',
267         'CursorStart'           => '<C-a>' }.each do |key, value|
268         if override = get_list_or_string("g:CommandT#{key}Map")
269           [override].flatten.each do |mapping|
270             map mapping, key
271           end
272         else
273           [value].flatten.each do |mapping|
274             map mapping, key unless mapping == '<Esc>' && (xterm? || vt100?)
275           end
276         end
277       end
278     end
280     # Returns the desired maximum number of matches, based on available
281     # vertical space and the g:CommandTMaxHeight option.
282     def match_limit
283       limit = VIM::Screen.lines - 5
284       limit = 1 if limit < 0
285       limit = [limit, @max_height].min if @max_height > 0
286       limit
287     end
289     def list_matches
290       matches = @finder.sorted_matches_for @prompt.abbrev, :limit => match_limit
291       @match_window.matches = matches
292     end
293   end # class Controller
294 end # module commandT
295 ruby/command-t/extconf.rb       [[[1
297 # Copyright 2010 Wincent Colaiuta. All rights reserved.
299 # Redistribution and use in source and binary forms, with or without
300 # modification, are permitted provided that the following conditions are met:
302 # 1. Redistributions of source code must retain the above copyright notice,
303 #    this list of conditions and the following disclaimer.
304 # 2. Redistributions in binary form must reproduce the above copyright notice,
305 #    this list of conditions and the following disclaimer in the documentation
306 #    and/or other materials provided with the distribution.
308 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
309 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
310 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
311 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
312 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
313 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
314 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
315 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
316 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
317 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
318 # POSSIBILITY OF SUCH DAMAGE.
320 require 'mkmf'
322 def missing item
323   puts "couldn't find #{item} (required)"
324   exit 1
327 have_header('ruby.h') or missing('ruby.h')
328 create_makefile('ext')
329 ruby/command-t/finder.rb        [[[1
331 # Copyright 2010 Wincent Colaiuta. All rights reserved.
333 # Redistribution and use in source and binary forms, with or without
334 # modification, are permitted provided that the following conditions are met:
336 # 1. Redistributions of source code must retain the above copyright notice,
337 #    this list of conditions and the following disclaimer.
338 # 2. Redistributions in binary form must reproduce the above copyright notice,
339 #    this list of conditions and the following disclaimer in the documentation
340 #    and/or other materials provided with the distribution.
342 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
343 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
344 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
345 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
346 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
347 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
348 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
349 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
350 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
351 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
352 # POSSIBILITY OF SUCH DAMAGE.
354 require 'command-t/ext' # CommandT::Matcher
355 require 'command-t/scanner'
357 module CommandT
358   # Encapsulates a Scanner instance (which builds up a list of available files
359   # in a directory) and a Matcher instance (which selects from that list based
360   # on a search string).
361   class Finder
362     def initialize path = Dir.pwd, options = {}
363       @scanner = Scanner.new path, options
364       @matcher = Matcher.new @scanner, options
365     end
367     # Options:
368     #   :limit (integer): limit the number of returned matches
369     def sorted_matches_for str, options = {}
370       @matcher.sorted_matches_for str, options
371     end
373     def flush
374       @scanner.flush
375     end
377     def path= path
378       @scanner.path = path
379     end
380   end # class Finder
381 end # CommandT
382 ruby/command-t/match_window.rb  [[[1
384 # Copyright 2010 Wincent Colaiuta. All rights reserved.
386 # Redistribution and use in source and binary forms, with or without
387 # modification, are permitted provided that the following conditions are met:
389 # 1. Redistributions of source code must retain the above copyright notice,
390 #    this list of conditions and the following disclaimer.
391 # 2. Redistributions in binary form must reproduce the above copyright notice,
392 #    this list of conditions and the following disclaimer in the documentation
393 #    and/or other materials provided with the distribution.
395 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
396 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
397 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
398 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
399 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
400 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
401 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
402 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
403 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
404 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
405 # POSSIBILITY OF SUCH DAMAGE.
407 require 'ostruct'
408 require 'command-t/settings'
410 module CommandT
411   class MatchWindow
412     @@selection_marker  = '> '
413     @@marker_length     = @@selection_marker.length
414     @@unselected_marker = ' ' * @@marker_length
416     def initialize options = {}
417       @prompt = options[:prompt]
419       # save existing window dimensions so we can restore them later
420       @windows = []
421       (0..(::VIM::Window.count - 1)).each do |i|
422         window = OpenStruct.new :index => i, :height => ::VIM::Window[i].height
423         @windows << window
424       end
426       # global settings (must manually save and restore)
427       @settings = Settings.new
428       ::VIM::set_option 'timeout'         # ensure mappings timeout
429       ::VIM::set_option 'timeoutlen=0'    # respond immediately to mappings
430       ::VIM::set_option 'nohlsearch'      # don't highlight search strings
431       ::VIM::set_option 'noinsertmode'    # don't make Insert mode the default
432       ::VIM::set_option 'noshowcmd'       # don't show command info on last line
433       ::VIM::set_option 'report=9999'     # don't show "X lines changed" reports
434       ::VIM::set_option 'sidescroll=0'    # don't sidescroll in jumps
435       ::VIM::set_option 'sidescrolloff=0' # don't sidescroll automatically
436       ::VIM::set_option 'noequalalways'   # don't auto-balance window sizes
438       # create match window and set it up
439       split_location = options[:match_window_at_top] ? 'topleft' : 'botright'
440       split_command = "silent! #{split_location} 1split GoToFile"
441       [
442         split_command,
443         'setlocal bufhidden=delete',  # delete buf when no longer displayed
444         'setlocal buftype=nofile',    # buffer is not related to any file
445         'setlocal nomodifiable',      # prevent manual edits
446         'setlocal noswapfile',        # don't create a swapfile
447         'setlocal nowrap',            # don't soft-wrap
448         'setlocal nonumber',          # don't show line numbers
449         'setlocal nolist',            # don't use List mode (visible tabs etc)
450         'setlocal foldcolumn=0',      # don't show a fold column at side
451         'setlocal foldlevel=99',      # don't fold anything
452         'setlocal nocursorline',      # don't highlight line cursor is on
453         'setlocal nospell',           # spell-checking off
454         'setlocal nobuflisted',       # don't show up in the buffer list
455         'setlocal textwidth=0'        # don't hard-wrap (break long lines)
456       ].each { |command| ::VIM::command command }
458       # sanity check: make sure the buffer really was created
459       raise "Can't find buffer" unless $curbuf.name.match /GoToFile/
461       # syntax coloring
462       if VIM::has_syntax?
463         ::VIM::command "syntax match CommandTSelection \"^#{@@selection_marker}.\\+$\""
464         ::VIM::command 'syntax match CommandTNoEntries "^-- NO MATCHES --$"'
465         ::VIM::command 'syntax match CommandTNoEntries "^-- NO SUCH FILE OR DIRECTORY --$"'
466         ::VIM::command 'highlight link CommandTSelection Visual'
467         ::VIM::command 'highlight link CommandTNoEntries Error'
468         ::VIM::evaluate 'clearmatches()'
470         # hide cursor
471         @cursor_highlight = get_cursor_highlight
472         hide_cursor
473       end
476       @has_focus  = false
477       @selection  = nil
478       @abbrev     = ''
479       @window     = $curwin
480       @buffer     = $curbuf
481     end
483     def close
484       ::VIM::command "bwipeout! #{@buffer.number}"
485       restore_window_dimensions
486       @settings.restore
487       @prompt.dispose
488       show_cursor
489     end
491     def add! char
492       @abbrev += char
493     end
495     def backspace!
496       @abbrev.chop!
497     end
499     def select_next
500       if @selection < @matches.length - 1
501         @selection += 1
502         print_match(@selection - 1) # redraw old selection (removes marker)
503         print_match(@selection)     # redraw new selection (adds marker)
504       else
505         # (possibly) loop or scroll
506       end
507     end
509     def select_prev
510       if @selection > 0
511         @selection -= 1
512         print_match(@selection + 1) # redraw old selection (removes marker)
513         print_match(@selection)     # redraw new selection (adds marker)
514       else
515         # (possibly) loop or scroll
516       end
517     end
519     def matches= matches
520       if matches != @matches
521         @matches =  matches
522         @selection = 0
523         print_matches
524       end
525     end
527     def focus
528       unless @has_focus
529         @has_focus = true
530         if VIM::has_syntax?
531           ::VIM::command 'highlight link CommandTSelection Search'
532         end
533       end
534     end
536     def unfocus
537       if @has_focus
538         @has_focus = false
539         if VIM::has_syntax?
540           ::VIM::command 'highlight link CommandTSelection Visual'
541         end
542       end
543     end
545     def find char
546       # is this a new search or the continuation of a previous one?
547       now = Time.now
548       if @last_key_time.nil? or @last_key_time < (now - 0.5)
549         @find_string = char
550       else
551         @find_string += char
552       end
553       @last_key_time = now
555       # see if there's anything up ahead that matches
556       @matches.each_with_index do |match, idx|
557         if match[0, @find_string.length].casecmp(@find_string) == 0
558           old_selection = @selection
559           @selection = idx
560           print_match(old_selection)  # redraw old selection (removes marker)
561           print_match(@selection)     # redraw new selection (adds marker)
562           break
563         end
564       end
565     end
567     # Returns the currently selected item as a String.
568     def selection
569       @matches[@selection]
570     end
572     def print_no_such_file_or_directory
573       print_error 'NO SUCH FILE OR DIRECTORY'
574     end
576   private
578     def print_error msg
579       return unless VIM::Window.select(@window)
580       unlock
581       clear
582       @window.height = 1
583       @buffer[1] = "-- #{msg} --"
584       lock
585     end
587     def restore_window_dimensions
588       # sort from tallest to shortest
589       @windows.sort! { |a, b| b.height <=> a.height }
591       # starting with the tallest ensures that there are no constraints
592       # preventing windows on the side of vertical splits from regaining
593       # their original full size
594       @windows.each do |w|
595         # beware: window may be nil
596         window = ::VIM::Window[w.index]
597         window.height = w.height if window
598       end
599     end
601     def match_text_for_idx idx
602       match = truncated_match @matches[idx]
603       if idx == @selection
604         prefix = @@selection_marker
605         suffix = padding_for_selected_match match
606       else
607         prefix = @@unselected_marker
608         suffix = ''
609       end
610       prefix + match + suffix
611     end
613     # Print just the specified match.
614     def print_match idx
615       return unless VIM::Window.select(@window)
616       unlock
617       @buffer[idx + 1] = match_text_for_idx idx
618       lock
619     end
621     # Print all matches.
622     def print_matches
623       match_count = @matches.length
624       if match_count == 0
625         print_error 'NO MATCHES'
626       else
627         return unless VIM::Window.select(@window)
628         unlock
629         clear
630         actual_lines = 1
631         @window_width = @window.width # update cached value
632         max_lines = VIM::Screen.lines - 5
633         max_lines = 1 if max_lines < 0
634         actual_lines = match_count > max_lines ? max_lines : match_count
635         @window.height = actual_lines
636         (1..actual_lines).each do |line|
637           idx = line - 1
638           if @buffer.count >= line
639             @buffer[line] = match_text_for_idx idx
640           else
641             @buffer.append line - 1, match_text_for_idx(idx)
642           end
643         end
644         lock
645       end
646     end
648     # Prepare padding for match text (trailing spaces) so that selection
649     # highlighting extends all the way to the right edge of the window.
650     def padding_for_selected_match str
651       len = str.length
652       if len >= @window_width - @@marker_length
653         ''
654       else
655         ' ' * (@window_width - @@marker_length - len)
656       end
657     end
659     # Convert "really/long/path" into "really...path" based on available
660     # window width.
661     def truncated_match str
662       len = str.length
663       available_width = @window_width - @@marker_length
664       return str if len <= available_width
665       left = (available_width / 2) - 1
666       right = (available_width / 2) - 2 + (available_width % 2)
667       str[0, left] + '...' + str[-right, right]
668     end
670     def clear
671       # range = % (whole buffer)
672       # action = d (delete)
673       # register = _ (black hole register, don't record deleted text)
674       ::VIM::command 'silent %d _'
675     end
677     def get_cursor_highlight
678       # as :highlight returns nothing and only prints,
679       # must redirect its output to a variable
680       ::VIM::command 'silent redir => g:command_t_cursor_highlight'
682       # force 0 verbosity to ensure origin information isn't printed as well
683       ::VIM::command 'silent! 0verbose highlight Cursor'
684       ::VIM::command 'silent redir END'
686       # there are 3 possible formats to check for, each needing to be
687       # transformed in a certain way in order to reapply the highlight:
688       #   Cursor xxx guifg=bg guibg=fg      -> :hi! Cursor guifg=bg guibg=fg
689       #   Cursor xxx links to SomethingElse -> :hi! link Cursor SomethingElse
690       #   Cursor xxx cleared                -> :hi! clear Cursor
691       highlight = ::VIM::evaluate 'g:command_t_cursor_highlight'
692       if highlight =~ /^Cursor\s+xxx\s+links to (\w+)/
693         "link Cursor #{$~[1]}"
694       elsif highlight =~ /^Cursor\s+xxx\s+cleared/
695         'clear Cursor'
696       elsif highlight =~ /Cursor\s+xxx\s+(.+)/
697         "Cursor #{$~[1]}"
698       else # likely cause E411 Cursor highlight group not found
699         nil
700       end
701     end
703     def hide_cursor
704       if @cursor_highlight
705         ::VIM::command 'highlight Cursor NONE'
706       end
707     end
709     def show_cursor
710       if @cursor_highlight
711         ::VIM::command "highlight #{@cursor_highlight}"
712       end
713     end
715     def lock
716       ::VIM::command 'setlocal nomodifiable'
717     end
719     def unlock
720       ::VIM::command 'setlocal modifiable'
721     end
722   end
724 ruby/command-t/prompt.rb        [[[1
726 # Copyright 2010 Wincent Colaiuta. All rights reserved.
728 # Redistribution and use in source and binary forms, with or without
729 # modification, are permitted provided that the following conditions are met:
731 # 1. Redistributions of source code must retain the above copyright notice,
732 #    this list of conditions and the following disclaimer.
733 # 2. Redistributions in binary form must reproduce the above copyright notice,
734 #    this list of conditions and the following disclaimer in the documentation
735 #    and/or other materials provided with the distribution.
737 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
738 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
739 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
740 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
741 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
742 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
743 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
744 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
745 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
746 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
747 # POSSIBILITY OF SUCH DAMAGE.
749 module CommandT
750   # Abuse the status line as a prompt.
751   class Prompt
752     attr_accessor :abbrev
754     def initialize
755       @abbrev     = ''  # abbreviation entered so far
756       @col        = 0   # cursor position
757       @has_focus  = false
758     end
760     # Erase whatever is displayed in the prompt line,
761     # effectively disposing of the prompt
762     def dispose
763       ::VIM::command 'echo'
764       ::VIM::command 'redraw'
765     end
767     # Clear any entered text.
768     def clear!
769       @abbrev = ''
770       @col    = 0
771       redraw
772     end
774     # Insert a character at (before) the current cursor position.
775     def add! char
776       left, cursor, right = abbrev_segments
777       @abbrev = left + char + cursor + right
778       @col += 1
779       redraw
780     end
782     # Delete a character to the left of the current cursor position.
783     def backspace!
784       if @col > 0
785         left, cursor, right = abbrev_segments
786         @abbrev = left.chop! + cursor + right
787         @col -= 1
788         redraw
789       end
790     end
792     # Delete a character at the current cursor position.
793     def delete!
794       if @col < @abbrev.length
795         left, cursor, right = abbrev_segments
796         @abbrev = left + right
797         redraw
798       end
799     end
801     def cursor_left
802       if @col > 0
803         @col -= 1
804         redraw
805       end
806     end
808     def cursor_right
809       if @col < @abbrev.length
810         @col += 1
811         redraw
812       end
813     end
815     def cursor_end
816       if @col < @abbrev.length
817         @col = @abbrev.length
818         redraw
819       end
820     end
822     def cursor_start
823       if @col != 0
824         @col = 0
825         redraw
826       end
827     end
829     def redraw
830       if @has_focus
831         prompt_highlight = 'Comment'
832         normal_highlight = 'None'
833         cursor_highlight = 'Underlined'
834       else
835         prompt_highlight = 'NonText'
836         normal_highlight = 'NonText'
837         cursor_highlight = 'NonText'
838       end
839       left, cursor, right = abbrev_segments
840       components = [prompt_highlight, '>>', 'None', ' ']
841       components += [normal_highlight, left] unless left.empty?
842       components += [cursor_highlight, cursor] unless cursor.empty?
843       components += [normal_highlight, right] unless right.empty?
844       components += [cursor_highlight, ' '] if cursor.empty?
845       set_status *components
846     end
848     def focus
849       unless @has_focus
850         @has_focus = true
851         redraw
852       end
853     end
855     def unfocus
856       if @has_focus
857         @has_focus = false
858         redraw
859       end
860     end
862   private
864     # Returns the @abbrev string divided up into three sections, any of
865     # which may actually be zero width, depending on the location of the
866     # cursor:
867     #   - left segment (to left of cursor)
868     #   - cursor segment (character at cursor)
869     #   - right segment (to right of cursor)
870     def abbrev_segments
871       left    = @abbrev[0, @col]
872       cursor  = @abbrev[@col, 1]
873       right   = @abbrev[(@col + 1)..-1] || ''
874       [left, cursor, right]
875     end
877     def set_status *args
878       # see ':help :echo' for why forcing a redraw here helps
879       # prevent the status line from getting inadvertantly cleared
880       # after our echo commands
881       ::VIM::command 'redraw'
882       while (highlight = args.shift) and  (text = args.shift) do
883         text = VIM::escape_for_single_quotes text
884         ::VIM::command "echohl #{highlight}"
885         ::VIM::command "echon '#{text}'"
886       end
887       ::VIM::command 'echohl None'
888     end
889   end # class Prompt
890 end # module CommandT
891 ruby/command-t/scanner.rb       [[[1
893 # Copyright 2010 Wincent Colaiuta. All rights reserved.
895 # Redistribution and use in source and binary forms, with or without
896 # modification, are permitted provided that the following conditions are met:
898 # 1. Redistributions of source code must retain the above copyright notice,
899 #    this list of conditions and the following disclaimer.
900 # 2. Redistributions in binary form must reproduce the above copyright notice,
901 #    this list of conditions and the following disclaimer in the documentation
902 #    and/or other materials provided with the distribution.
904 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
905 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
906 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
907 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
908 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
909 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
910 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
911 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
912 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
913 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
914 # POSSIBILITY OF SUCH DAMAGE.
916 require 'command-t/vim'
918 module CommandT
919   # Reads the current directory recursively for the paths to all regular files.
920   class Scanner
921     class FileLimitExceeded < ::RuntimeError; end
923     def initialize path = Dir.pwd, options = {}
924       @path                 = path
925       @max_depth            = options[:max_depth] || 15
926       @max_files            = options[:max_files] || 10_000
927       @scan_dot_directories = options[:scan_dot_directories] || false
928     end
930     def paths
931       return @paths unless @paths.nil?
932       begin
933         @paths = []
934         @depth = 0
935         @files = 0
936         @prefix_len = @path.chomp('/').length
937         add_paths_for_directory @path, @paths
938       rescue FileLimitExceeded
939       end
940       @paths
941     end
943     def flush
944       @paths = nil
945     end
947     def path= str
948       if @path != str
949         @path = str
950         flush
951       end
952     end
954   private
956     def path_excluded? path
957       # first strip common prefix (@path) from path to match VIM's behavior
958       path = path[(@prefix_len + 1)..-1]
959       path = VIM::escape_for_single_quotes path
960       ::VIM::evaluate("empty(expand(fnameescape('#{path}')))").to_i == 1
961     end
963     def add_paths_for_directory dir, accumulator
964       Dir.foreach(dir) do |entry|
965         next if ['.', '..'].include?(entry)
966         path = File.join(dir, entry)
967         unless path_excluded?(path)
968           if File.file?(path)
969             @files += 1
970             raise FileLimitExceeded if @files > @max_files
971             accumulator << path[@prefix_len + 1..-1]
972           elsif File.directory?(path)
973             next if @depth >= @max_depth
974             next if (entry.match(/\A\./) && !@scan_dot_directories)
975             @depth += 1
976             add_paths_for_directory path, accumulator
977             @depth -= 1
978           end
979         end
980       end
981     rescue Errno::EACCES
982       # skip over directories for which we don't have access
983     end
984   end # class Scanner
985 end # module CommandT
986 ruby/command-t/settings.rb      [[[1
988 # Copyright 2010 Wincent Colaiuta. All rights reserved.
990 # Redistribution and use in source and binary forms, with or without
991 # modification, are permitted provided that the following conditions are met:
993 # 1. Redistributions of source code must retain the above copyright notice,
994 #    this list of conditions and the following disclaimer.
995 # 2. Redistributions in binary form must reproduce the above copyright notice,
996 #    this list of conditions and the following disclaimer in the documentation
997 #    and/or other materials provided with the distribution.
999 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1000 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1001 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1002 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
1003 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1004 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1005 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1006 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1007 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1008 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1009 # POSSIBILITY OF SUCH DAMAGE.
1011 module CommandT
1012   # Convenience class for saving and restoring global settings.
1013   class Settings
1014     def initialize
1015       save
1016     end
1018     def save
1019       @timeoutlen     = get_number 'timeoutlen'
1020       @report         = get_number 'report'
1021       @sidescroll     = get_number 'sidescroll'
1022       @sidescrolloff  = get_number 'sidescrolloff'
1023       @timeout        = get_bool 'timeout'
1024       @equalalways    = get_bool 'equalalways'
1025       @hlsearch       = get_bool 'hlsearch'
1026       @insertmode     = get_bool 'insertmode'
1027       @showcmd        = get_bool 'showcmd'
1028     end
1030     def restore
1031       set_number 'timeoutlen', @timeoutlen
1032       set_number 'report', @report
1033       set_number 'sidescroll', @sidescroll
1034       set_number 'sidescrolloff', @sidescrolloff
1035       set_bool 'timeout', @timeout
1036       set_bool 'equalalways', @equalalways
1037       set_bool 'hlsearch', @hlsearch
1038       set_bool 'insertmode', @insertmode
1039       set_bool 'showcmd', @showcmd
1040     end
1042   private
1044     def get_number setting
1045       ::VIM::evaluate("&#{setting}").to_i
1046     end
1048     def get_bool setting
1049       ::VIM::evaluate("&#{setting}").to_i == 1
1050     end
1052     def set_number setting, value
1053       ::VIM::set_option "#{setting}=#{value}"
1054     end
1056     def set_bool setting, value
1057       if value
1058         ::VIM::set_option setting
1059       else
1060         ::VIM::set_option "no#{setting}"
1061       end
1062     end
1063   end # class Settings
1064 end # module CommandT
1065 ruby/command-t/stub.rb  [[[1
1067 # Copyright 2010 Wincent Colaiuta. All rights reserved.
1069 # Redistribution and use in source and binary forms, with or without
1070 # modification, are permitted provided that the following conditions are met:
1072 # 1. Redistributions of source code must retain the above copyright notice,
1073 #    this list of conditions and the following disclaimer.
1074 # 2. Redistributions in binary form must reproduce the above copyright notice,
1075 #    this list of conditions and the following disclaimer in the documentation
1076 #    and/or other materials provided with the distribution.
1078 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1079 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1080 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1081 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
1082 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1083 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1084 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1085 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1086 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1087 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1088 # POSSIBILITY OF SUCH DAMAGE.
1090 module CommandT
1091   class Stub
1092     @@load_error = ['command-t.vim could not load the C extension',
1093                     'Please see INSTALLATION and TROUBLE-SHOOTING in the help',
1094                     'For more information type:    :help command-t']
1096     def show
1097       warn *@@load_error
1098     end
1100     def flush
1101       warn *@@load_error
1102     end
1104   private
1106     def warn *msg
1107       ::VIM::command 'echohl WarningMsg'
1108       msg.each { |m| ::VIM::command "echo '#{m}'" }
1109       ::VIM::command 'echohl none'
1110     end
1111   end # class Stub
1112 end # module CommandT
1113 ruby/command-t/vim/screen.rb    [[[1
1115 # Copyright 2010 Wincent Colaiuta. All rights reserved.
1117 # Redistribution and use in source and binary forms, with or without
1118 # modification, are permitted provided that the following conditions are met:
1120 # 1. Redistributions of source code must retain the above copyright notice,
1121 #    this list of conditions and the following disclaimer.
1122 # 2. Redistributions in binary form must reproduce the above copyright notice,
1123 #    this list of conditions and the following disclaimer in the documentation
1124 #    and/or other materials provided with the distribution.
1126 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1127 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1128 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1129 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
1130 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1131 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1132 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1133 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1134 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1135 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1136 # POSSIBILITY OF SUCH DAMAGE.
1138 module CommandT
1139   module VIM
1140     module Screen
1141       def self.lines
1142         ::VIM::evaluate('&lines').to_i
1143       end
1144     end # module Screen
1145   end # module VIM
1146 end # module CommandT
1147 ruby/command-t/vim/window.rb    [[[1
1149 # Copyright 2010 Wincent Colaiuta. All rights reserved.
1151 # Redistribution and use in source and binary forms, with or without
1152 # modification, are permitted provided that the following conditions are met:
1154 # 1. Redistributions of source code must retain the above copyright notice,
1155 #    this list of conditions and the following disclaimer.
1156 # 2. Redistributions in binary form must reproduce the above copyright notice,
1157 #    this list of conditions and the following disclaimer in the documentation
1158 #    and/or other materials provided with the distribution.
1160 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1161 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1162 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1163 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
1164 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1165 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1166 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1167 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1168 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1169 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1170 # POSSIBILITY OF SUCH DAMAGE.
1172 module CommandT
1173   module VIM
1174     class Window
1175       def self.select window
1176         return true if $curwin == window
1177         initial = $curwin
1178         while true do
1179           ::VIM::command 'wincmd w'           # cycle through windows
1180           return true if $curwin == window    # have selected desired window
1181           return false if $curwin == initial  # have already looped through all
1182         end
1183       end
1184     end # class Window
1185   end # module VIM
1186 end # module CommandT
1187 ruby/command-t/vim.rb   [[[1
1189 # Copyright 2010 Wincent Colaiuta. All rights reserved.
1191 # Redistribution and use in source and binary forms, with or without
1192 # modification, are permitted provided that the following conditions are met:
1194 # 1. Redistributions of source code must retain the above copyright notice,
1195 #    this list of conditions and the following disclaimer.
1196 # 2. Redistributions in binary form must reproduce the above copyright notice,
1197 #    this list of conditions and the following disclaimer in the documentation
1198 #    and/or other materials provided with the distribution.
1200 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1201 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1202 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1203 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
1204 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1205 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1206 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1207 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1208 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1209 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1210 # POSSIBILITY OF SUCH DAMAGE.
1212 require 'command-t/vim/screen'
1213 require 'command-t/vim/window'
1215 module CommandT
1216   module VIM
1217     def self.has_syntax?
1218       ::VIM::evaluate('has("syntax")').to_i != 0
1219     end
1221     def self.pwd
1222       ::VIM::evaluate 'getcwd()'
1223     end
1225     # Escape a string for safe inclusion in a Vim single-quoted string
1226     # (single quotes escaped by doubling, everything else is literal)
1227     def self.escape_for_single_quotes str
1228       str.gsub "'", "''"
1229     end
1230   end # module VIM
1231 end # module CommandT
1232 ruby/command-t/ext.c    [[[1
1234 // Copyright 2010 Wincent Colaiuta. All rights reserved.
1236 // Redistribution and use in source and binary forms, with or without
1237 // modification, are permitted provided that the following conditions are met:
1239 // 1. Redistributions of source code must retain the above copyright notice,
1240 //    this list of conditions and the following disclaimer.
1241 // 2. Redistributions in binary form must reproduce the above copyright notice,
1242 //    this list of conditions and the following disclaimer in the documentation
1243 //    and/or other materials provided with the distribution.
1245 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1246 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1247 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1248 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
1249 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1250 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1251 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1252 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1253 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1254 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1255 // POSSIBILITY OF SUCH DAMAGE.
1257 #include "match.h"
1258 #include "matcher.h"
1260 VALUE mCommandT         = 0; // module CommandT
1261 VALUE cCommandTMatch    = 0; // class CommandT::Match
1262 VALUE cCommandTMatcher  = 0; // class CommandT::Matcher
1264 VALUE CommandT_option_from_hash(const char *option, VALUE hash)
1266     if (NIL_P(hash))
1267         return Qnil;
1268     VALUE key = ID2SYM(rb_intern(option));
1269     if (rb_funcall(hash, rb_intern("has_key?"), 1, key) == Qtrue)
1270         return rb_hash_aref(hash, key);
1271     else
1272         return Qnil;
1275 void Init_ext()
1277     // module CommandT
1278     mCommandT = rb_define_module("CommandT");
1280     // class CommandT::Match
1281     cCommandTMatch = rb_define_class_under(mCommandT, "Match", rb_cObject);
1283     // methods
1284     rb_define_method(cCommandTMatch, "initialize", CommandTMatch_initialize, -1);
1285     rb_define_method(cCommandTMatch, "matches?", CommandTMatch_matches, 0);
1286     rb_define_method(cCommandTMatch, "to_s", CommandTMatch_to_s, 0);
1288     // attributes
1289     rb_define_attr(cCommandTMatch, "score", Qtrue, Qfalse); // reader: true, writer: false
1291     // class CommandT::Matcher
1292     cCommandTMatcher = rb_define_class_under(mCommandT, "Matcher", rb_cObject);
1294     // methods
1295     rb_define_method(cCommandTMatcher, "initialize", CommandTMatcher_initialize, -1);
1296     rb_define_method(cCommandTMatcher, "sorted_matches_for", CommandTMatcher_sorted_matchers_for, 2);
1297     rb_define_method(cCommandTMatcher, "matches_for", CommandTMatcher_matches_for, 1);
1299 ruby/command-t/match.c  [[[1
1301 // Copyright 2010 Wincent Colaiuta. All rights reserved.
1303 // Redistribution and use in source and binary forms, with or without
1304 // modification, are permitted provided that the following conditions are met:
1306 // 1. Redistributions of source code must retain the above copyright notice,
1307 //    this list of conditions and the following disclaimer.
1308 // 2. Redistributions in binary form must reproduce the above copyright notice,
1309 //    this list of conditions and the following disclaimer in the documentation
1310 //    and/or other materials provided with the distribution.
1312 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1313 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1314 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1315 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
1316 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1317 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1318 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1319 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1320 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1321 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1322 // POSSIBILITY OF SUCH DAMAGE.
1324 #include "match.h"
1325 #include "ext.h"
1326 #include "ruby_compat.h"
1328 // use a struct to make passing params during recursion easier
1329 typedef struct
1331     char    *str_p;                 // pointer to string to be searched
1332     long    str_len;                // length of same
1333     char    *abbrev_p;              // pointer to search string (abbreviation)
1334     long    abbrev_len;             // length of same
1335     double  max_score_per_char;
1336     int     dot_file;               // boolean: true if str is a dot-file
1337     int     always_show_dot_files;  // boolean
1338     int     never_show_dot_files;   // boolean
1339 } matchinfo_t;
1341 double recursive_match(matchinfo_t *m,  // sharable meta-data
1342                        long str_idx,    // where in the path string to start
1343                        long abbrev_idx, // where in the search string to start
1344                        long last_idx,   // location of last matched character
1345                        double score)    // cumulative score so far
1347     double seen_score = 0;      // remember best score seen via recursion
1348     int dot_file_match = 0;     // true if abbrev matches a dot-file
1349     int dot_search = 0;         // true if searching for a dot
1351     for (long i = abbrev_idx; i < m->abbrev_len; i++)
1352     {
1353         char c = m->abbrev_p[i];
1354         if (c == '.')
1355             dot_search = 1;
1356         int found = 0;
1357         for (long j = str_idx; j < m->str_len; j++, str_idx++)
1358         {
1359             char d = m->str_p[j];
1360             if (d == '.')
1361             {
1362                 if (j == 0 || m->str_p[j - 1] == '/')
1363                 {
1364                     m->dot_file = 1;        // this is a dot-file
1365                     if (dot_search)         // and we are searching for a dot
1366                         dot_file_match = 1; // so this must be a match
1367                 }
1368             }
1369             else if (d >= 'A' && d <= 'Z')
1370                 d += 'a' - 'A'; // add 32 to downcase
1371             if (c == d)
1372             {
1373                 found = 1;
1374                 dot_search = 0;
1376                 // calculate score
1377                 double score_for_char = m->max_score_per_char;
1378                 long distance = j - last_idx;
1379                 if (distance > 1)
1380                 {
1381                     double factor = 1.0;
1382                     char last = m->str_p[j - 1];
1383                     char curr = m->str_p[j]; // case matters, so get again
1384                     if (last == '/')
1385                         factor = 0.9;
1386                     else if (last == '-' ||
1387                             last == '_' ||
1388                             last == ' ' ||
1389                             (last >= '0' && last <= '9'))
1390                         factor = 0.8;
1391                     else if (last >= 'a' && last <= 'z' &&
1392                             curr >= 'A' && curr <= 'Z')
1393                         factor = 0.8;
1394                     else if (last == '.')
1395                         factor = 0.7;
1396                     else
1397                         // if no "special" chars behind char, factor diminishes
1398                         // as distance from last matched char increases
1399                         factor = (1.0 / distance) * 0.75;
1400                     score_for_char *= factor;
1401                 }
1403                 if (++j < m->str_len)
1404                 {
1405                     // bump cursor one char to the right and
1406                     // use recursion to try and find a better match
1407                     double sub_score = recursive_match(m, j, i, last_idx, score);
1408                     if (sub_score > seen_score)
1409                         seen_score = sub_score;
1410                 }
1412                 score += score_for_char;
1413                 last_idx = str_idx++;
1414                 break;
1415             }
1416         }
1417         if (!found)
1418             return 0.0;
1419     }
1420     if (m->dot_file)
1421     {
1422         if (m->never_show_dot_files ||
1423             (!dot_file_match && !m->always_show_dot_files))
1424             return 0.0;
1425     }
1426     return (score > seen_score) ? score : seen_score;
1429 // Match.new abbrev, string, options = {}
1430 VALUE CommandTMatch_initialize(int argc, VALUE *argv, VALUE self)
1432     // process arguments: 2 mandatory, 1 optional
1433     VALUE str, abbrev, options;
1434     if (rb_scan_args(argc, argv, "21", &str, &abbrev, &options) == 2)
1435         options = Qnil;
1436     str             = StringValue(str);
1437     abbrev          = StringValue(abbrev); // already downcased by caller
1439     // check optional options hash for overrides
1440     VALUE always_show_dot_files = CommandT_option_from_hash("always_show_dot_files", options);
1441     VALUE never_show_dot_files = CommandT_option_from_hash("never_show_dot_files", options);
1443     matchinfo_t m;
1444     m.str_p                 = RSTRING_PTR(str);
1445     m.str_len               = RSTRING_LEN(str);
1446     m.abbrev_p              = RSTRING_PTR(abbrev);
1447     m.abbrev_len            = RSTRING_LEN(abbrev);
1448     m.max_score_per_char    = (1.0 / m.str_len + 1.0 / m.abbrev_len) / 2;
1449     m.dot_file              = 0;
1450     m.always_show_dot_files = always_show_dot_files == Qtrue;
1451     m.never_show_dot_files  = never_show_dot_files == Qtrue;
1453     // calculate score
1454     double score = 1.0;
1455     if (m.abbrev_len == 0) // special case for zero-length search string
1456     {
1457         // filter out dot files
1458         if (!m.always_show_dot_files)
1459         {
1460             for (long i = 0; i < m.str_len; i++)
1461             {
1462                 char c = m.str_p[i];
1463                 if (c == '.' && (i == 0 || m.str_p[i - 1] == '/'))
1464                 {
1465                     score = 0.0;
1466                     break;
1467                 }
1468             }
1469         }
1470     }
1471     else // normal case
1472         score = recursive_match(&m, 0, 0, 0, 0.0);
1474     // clean-up and final book-keeping
1475     rb_iv_set(self, "@score", rb_float_new(score));
1476     rb_iv_set(self, "@str", str);
1477     return Qnil;
1480 VALUE CommandTMatch_matches(VALUE self)
1482     double score = NUM2DBL(rb_iv_get(self, "@score"));
1483     return score > 0 ? Qtrue : Qfalse;
1486 VALUE CommandTMatch_to_s(VALUE self)
1488     return rb_iv_get(self, "@str");
1490 ruby/command-t/matcher.c        [[[1
1492 // Copyright 2010 Wincent Colaiuta. All rights reserved.
1494 // Redistribution and use in source and binary forms, with or without
1495 // modification, are permitted provided that the following conditions are met:
1497 // 1. Redistributions of source code must retain the above copyright notice,
1498 //    this list of conditions and the following disclaimer.
1499 // 2. Redistributions in binary form must reproduce the above copyright notice,
1500 //    this list of conditions and the following disclaimer in the documentation
1501 //    and/or other materials provided with the distribution.
1503 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1504 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1505 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1506 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
1507 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1508 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1509 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1510 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1511 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1512 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1513 // POSSIBILITY OF SUCH DAMAGE.
1515 #include <stdlib.h> /* for qsort() */
1516 #include <string.h> /* for strcmp() */
1517 #include "matcher.h"
1518 #include "ext.h"
1519 #include "ruby_compat.h"
1521 // comparison function for use with qsort
1522 int comp_alpha(const void *a, const void *b)
1524     VALUE a_val = *(VALUE *)a;
1525     VALUE b_val = *(VALUE *)b;
1526     ID to_s = rb_intern("to_s");
1528     VALUE a_str = rb_funcall(a_val, to_s, 0);
1529     VALUE b_str = rb_funcall(b_val, to_s, 0);
1530     char *a_p = RSTRING_PTR(a_str);
1531     long a_len = RSTRING_LEN(a_str);
1532     char *b_p = RSTRING_PTR(b_str);
1533     long b_len = RSTRING_LEN(b_str);
1534     int order = 0;
1535     if (a_len > b_len)
1536     {
1537         order = strncmp(a_p, b_p, b_len);
1538         if (order == 0)
1539             order = 1; // shorter string (b) wins
1540     }
1541     else if (a_len < b_len)
1542     {
1543         order = strncmp(a_p, b_p, a_len);
1544         if (order == 0)
1545             order = -1; // shorter string (a) wins
1546     }
1547     else
1548         order = strncmp(a_p, b_p, a_len);
1549     return order;
1552 // comparison function for use with qsort
1553 int comp_score(const void *a, const void *b)
1555     VALUE a_val = *(VALUE *)a;
1556     VALUE b_val = *(VALUE *)b;
1557     ID score = rb_intern("score");
1558     double a_score = RFLOAT_VALUE(rb_funcall(a_val, score, 0));
1559     double b_score = RFLOAT_VALUE(rb_funcall(b_val, score, 0));
1560     if (a_score > b_score)
1561         return -1; // a scores higher, a should appear sooner
1562     else if (a_score < b_score)
1563         return 1;  // b scores higher, a should appear later
1564     else
1565         return comp_alpha(a, b);
1568 VALUE CommandTMatcher_initialize(int argc, VALUE *argv, VALUE self)
1570     // process arguments: 1 mandatory, 1 optional
1571     VALUE scanner, options;
1572     if (rb_scan_args(argc, argv, "11", &scanner, &options) == 1)
1573         options = Qnil;
1574     if (NIL_P(scanner))
1575         rb_raise(rb_eArgError, "nil scanner");
1576     rb_iv_set(self, "@scanner", scanner);
1578     // check optional options hash for overrides
1579     VALUE always_show_dot_files = CommandT_option_from_hash("always_show_dot_files", options);
1580     if (always_show_dot_files != Qtrue)
1581         always_show_dot_files = Qfalse;
1582     VALUE never_show_dot_files = CommandT_option_from_hash("never_show_dot_files", options);
1583     if (never_show_dot_files != Qtrue)
1584         never_show_dot_files = Qfalse;
1585     rb_iv_set(self, "@always_show_dot_files", always_show_dot_files);
1586     rb_iv_set(self, "@never_show_dot_files", never_show_dot_files);
1587     return Qnil;
1590 VALUE CommandTMatcher_sorted_matchers_for(VALUE self, VALUE abbrev, VALUE options)
1592     // process optional options hash
1593     VALUE limit_option = CommandT_option_from_hash("limit", options);
1595     // get unsorted matches
1596     VALUE matches = CommandTMatcher_matches_for(self, abbrev);
1598     abbrev = StringValue(abbrev);
1599     if (RSTRING_LEN(abbrev) == 0 ||
1600         (RSTRING_LEN(abbrev) == 1 && RSTRING_PTR(abbrev)[0] == '.'))
1601         // alphabetic order if search string is only "" or "."
1602         qsort(RARRAY_PTR(matches), RARRAY_LEN(matches), sizeof(VALUE), comp_alpha);
1603     else
1604         // for all other non-empty search strings, sort by score
1605         qsort(RARRAY_PTR(matches), RARRAY_LEN(matches), sizeof(VALUE), comp_score);
1607     // apply optional limit option
1608     long limit = NIL_P(limit_option) ? 0 : NUM2LONG(limit_option);
1609     if (limit == 0 || RARRAY_LEN(matches)< limit)
1610         limit = RARRAY_LEN(matches);
1612     // will return an array of strings, not an array of Match objects
1613     for (long i = 0; i < limit; i++)
1614     {
1615         VALUE str = rb_funcall(RARRAY_PTR(matches)[i], rb_intern("to_s"), 0);
1616         RARRAY_PTR(matches)[i] = str;
1617     }
1619     // trim off any items beyond the limit
1620     if (limit < RARRAY_LEN(matches))
1621         (void)rb_funcall(matches, rb_intern("slice!"), 2, LONG2NUM(limit),
1622             LONG2NUM(RARRAY_LEN(matches) - limit));
1623     return matches;
1626 VALUE CommandTMatcher_matches_for(VALUE self, VALUE abbrev)
1628     if (NIL_P(abbrev))
1629         rb_raise(rb_eArgError, "nil abbrev");
1630     VALUE matches = rb_ary_new();
1631     VALUE scanner = rb_iv_get(self, "@scanner");
1632     VALUE always_show_dot_files = rb_iv_get(self, "@always_show_dot_files");
1633     VALUE never_show_dot_files = rb_iv_get(self, "@never_show_dot_files");
1634     VALUE options = Qnil;
1635     if (always_show_dot_files == Qtrue)
1636     {
1637         options = rb_hash_new();
1638         rb_hash_aset(options, ID2SYM(rb_intern("always_show_dot_files")), always_show_dot_files);
1639     }
1640     else if (never_show_dot_files == Qtrue)
1641     {
1642         options = rb_hash_new();
1643         rb_hash_aset(options, ID2SYM(rb_intern("never_show_dot_files")), never_show_dot_files);
1644     }
1645     abbrev = rb_funcall(abbrev, rb_intern("downcase"), 0);
1646     VALUE paths = rb_funcall(scanner, rb_intern("paths"), 0);
1647     for (long i = 0, max = RARRAY_LEN(paths); i < max; i++)
1648     {
1649         VALUE path = RARRAY_PTR(paths)[i];
1650         VALUE match = rb_funcall(cCommandTMatch, rb_intern("new"), 3, path, abbrev, options);
1651         if (rb_funcall(match, rb_intern("matches?"), 0) == Qtrue)
1652             rb_funcall(matches, rb_intern("push"), 1, match);
1653     }
1654     return matches;
1656 ruby/command-t/ext.h    [[[1
1658 // Copyright 2010 Wincent Colaiuta. All rights reserved.
1660 // Redistribution and use in source and binary forms, with or without
1661 // modification, are permitted provided that the following conditions are met:
1663 // 1. Redistributions of source code must retain the above copyright notice,
1664 //    this list of conditions and the following disclaimer.
1665 // 2. Redistributions in binary form must reproduce the above copyright notice,
1666 //    this list of conditions and the following disclaimer in the documentation
1667 //    and/or other materials provided with the distribution.
1669 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1670 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1671 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1672 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
1673 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1674 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1675 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1676 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1677 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1678 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1679 // POSSIBILITY OF SUCH DAMAGE.
1681 #include <ruby.h>
1683 extern VALUE mCommandT;         // module CommandT
1684 extern VALUE cCommandTMatch;    // class CommandT::Match
1685 extern VALUE cCommandTMatcher;  // class CommandT::Matcher
1687 // Encapsulates common pattern of checking for an option in an optional
1688 // options hash. The hash itself may be nil, but an exception will be
1689 // raised if it is not nil and not a hash.
1690 VALUE CommandT_option_from_hash(const char *option, VALUE hash);
1692 // Debugging macro.
1693 #define ruby_inspect(obj) rb_funcall(rb_mKernel, rb_intern("p"), 1, obj)
1694 ruby/command-t/match.h  [[[1
1696 // Copyright 2010 Wincent Colaiuta. All rights reserved.
1698 // Redistribution and use in source and binary forms, with or without
1699 // modification, are permitted provided that the following conditions are met:
1701 // 1. Redistributions of source code must retain the above copyright notice,
1702 //    this list of conditions and the following disclaimer.
1703 // 2. Redistributions in binary form must reproduce the above copyright notice,
1704 //    this list of conditions and the following disclaimer in the documentation
1705 //    and/or other materials provided with the distribution.
1707 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1708 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1709 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1710 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
1711 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1712 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1713 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1714 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1715 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1716 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1717 // POSSIBILITY OF SUCH DAMAGE.
1719 #include <ruby.h>
1721 extern VALUE CommandTMatch_initialize(int argc, VALUE *argv, VALUE self);
1722 extern VALUE CommandTMatch_matches(VALUE self);
1723 extern VALUE CommandTMatch_score(VALUE self);
1724 extern VALUE CommandTMatch_to_s(VALUE self);
1725 ruby/command-t/matcher.h        [[[1
1727 // Copyright 2010 Wincent Colaiuta. All rights reserved.
1729 // Redistribution and use in source and binary forms, with or without
1730 // modification, are permitted provided that the following conditions are met:
1732 // 1. Redistributions of source code must retain the above copyright notice,
1733 //    this list of conditions and the following disclaimer.
1734 // 2. Redistributions in binary form must reproduce the above copyright notice,
1735 //    this list of conditions and the following disclaimer in the documentation
1736 //    and/or other materials provided with the distribution.
1738 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1739 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1740 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1741 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
1742 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1743 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1744 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1745 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1746 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1747 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1748 // POSSIBILITY OF SUCH DAMAGE.
1750 #include <ruby.h>
1752 extern VALUE CommandTMatcher_initialize(int argc, VALUE *argv, VALUE self);
1753 extern VALUE CommandTMatcher_sorted_matchers_for(VALUE self, VALUE abbrev, VALUE options);
1755 // most likely the function will be subsumed by the sorted_matcher_for function
1756 extern VALUE CommandTMatcher_matches_for(VALUE self, VALUE abbrev);
1757 ruby/command-t/ruby_compat.h    [[[1
1759 // Copyright 2010 Wincent Colaiuta. All rights reserved.
1761 // Redistribution and use in source and binary forms, with or without
1762 // modification, are permitted provided that the following conditions are met:
1764 // 1. Redistributions of source code must retain the above copyright notice,
1765 //    this list of conditions and the following disclaimer.
1766 // 2. Redistributions in binary form must reproduce the above copyright notice,
1767 //    this list of conditions and the following disclaimer in the documentation
1768 //    and/or other materials provided with the distribution.
1770 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1771 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1772 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1773 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
1774 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1775 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1776 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1777 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1778 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1779 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1780 // POSSIBILITY OF SUCH DAMAGE.
1782 #include <ruby.h>
1784 // for compatibility with older versions of Ruby which don't declare RSTRING_PTR
1785 #ifndef RSTRING_PTR
1786 #define RSTRING_PTR(s) (RSTRING(s)->ptr)
1787 #endif
1789 // for compatibility with older versions of Ruby which don't declare RSTRING_LEN
1790 #ifndef RSTRING_LEN
1791 #define RSTRING_LEN(s) (RSTRING(s)->len)
1792 #endif
1794 // for compatibility with older versions of Ruby which don't declare RARRAY_PTR
1795 #ifndef RARRAY_PTR
1796 #define RARRAY_PTR(a) (RARRAY(a)->ptr)
1797 #endif
1799 // for compatibility with older versions of Ruby which don't declare RARRAY_LEN
1800 #ifndef RARRAY_LEN
1801 #define RARRAY_LEN(a) (RARRAY(a)->len)
1802 #endif
1804 // for compatibility with older versions of Ruby which don't declare RFLOAT_VALUE
1805 #ifndef RFLOAT_VALUE
1806 #define RFLOAT_VALUE(f) (RFLOAT(f)->value)
1807 #endif
1808 ruby/command-t/depend   [[[1
1810 # Copyright 2010 Wincent Colaiuta. All rights reserved.
1812 # Redistribution and use in source and binary forms, with or without
1813 # modification, are permitted provided that the following conditions are met:
1815 # 1. Redistributions of source code must retain the above copyright notice,
1816 #    this list of conditions and the following disclaimer.
1817 # 2. Redistributions in binary form must reproduce the above copyright notice,
1818 #    this list of conditions and the following disclaimer in the documentation
1819 #    and/or other materials provided with the distribution.
1821 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1822 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1823 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1824 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
1825 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1826 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1827 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1828 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1829 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1830 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1831 # POSSIBILITY OF SUCH DAMAGE.
1833 CFLAGS += -std=c99 -Wall -Wextra -Wno-unused-parameter
1834 doc/command-t.txt       [[[1
1836 *command-t.txt* Command-T plug-in for Vim         *command-t*
1838 CONTENTS                                        *command-t-contents*
1840  1. Introduction            |command-t-intro|
1841  2. Requirements            |command-t-requirements|
1842  3. Installation            |command-t-installation|
1843  3. Managing using Pathogen |command-t-pathogen|
1844  4. Trouble-shooting        |command-t-trouble-shooting|
1845  5. Usage                   |command-t-usage|
1846  6. Commands                |command-t-commands|
1847  7. Mappings                |command-t-mappings|
1848  8. Options                 |command-t-options|
1849  9. Authors                 |command-t-authors|
1850 10. Website                 |command-t-website|
1851 11. Donations               |command-t-donations|
1852 12. License                 |command-t-license|
1853 13. History                 |command-t-history|
1856 INTRODUCTION                                    *command-t-intro*
1858 The Command-T plug-in provides an extremely fast, intuitive mechanism for
1859 opening files with a minimal number of keystrokes. It's named "Command-T"
1860 because it is inspired by the "Go to File" window bound to Command-T in
1861 TextMate.
1863 Files are selected by typing characters that appear in their paths, and are
1864 ordered by an algorithm which knows that characters that appear in certain
1865 locations (for example, immediately after a path separator) should be given
1866 more weight.
1868 To search efficiently, especially in large projects, you should adopt a
1869 "path-centric" rather than a "filename-centric" mentality. That is you should
1870 think more about where the desired file is found rather than what it is
1871 called. This means narrowing your search down by including some characters
1872 from the upper path components rather than just entering characters from the
1873 filename itself.
1875 Screencasts demonstrating the plug-in can be viewed at:
1877   https://wincent.com/products/command-t
1880 REQUIREMENTS                                    *command-t-requirements*
1882 The plug-in requires Vim compiled with Ruby support, a compatible Ruby
1883 installation at the operating system level, and a C compiler to build
1884 the Ruby extension.
1887 1. Vim compiled with Ruby support
1889 You can check for Ruby support by launching Vim with the --version switch:
1891   vim --version
1893 If "+ruby" appears in the version information then your version of Vim has
1894 Ruby support.
1896 Another way to check is to simply try using the :ruby command from within Vim
1897 itself:
1899   :ruby 1
1901 If your Vim lacks support you'll see an error message like this:
1903   E319: Sorry, the command is not available in this version
1905 The version of Vim distributed with Mac OS X does not include Ruby support,
1906 while MacVim does; it is available from:
1908   http://github.com/b4winckler/macvim/downloads
1910 For Windows users, the Vim 7.2 executable available from www.vim.org does
1911 include Ruby support, and is recommended over version 7.3 (which links against
1912 Ruby 1.9, but apparently has some bugs that need to be resolved).
1915 2. Ruby
1917 In addition to having Ruby support in Vim, your system itself must have a
1918 compatible Ruby install. "Compatible" means the same version as Vim itself
1919 links against. If you use a different version then Command-T is unlikely
1920 to work (see TROUBLE-SHOOTING below).
1922 On Mac OS X Snow Leopard, the system comes with Ruby 1.8.7 and all recent
1923 versions of MacVim (the 7.2 snapshots and 7.3) are linked against it.
1925 On Linux and similar platforms, the linked version of Ruby will depend on
1926 your distribution. You can usually find this out by examining the
1927 compilation and linking flags displayed by the |:version| command in Vim, and
1928 by looking at the output of:
1930   :ruby puts RUBY_VERSION
1932 A suitable Ruby environment for Windows can be installed using the Ruby
1933 1.8.7-p299 RubyInstaller available at:
1935   http://rubyinstaller.org/downloads/archives
1937 If using RubyInstaller be sure to download the installer executable, not the
1938 7-zip archive. When installing mark the checkbox "Add Ruby executables to your
1939 PATH" so that Vim can find them.
1942 3. C compiler
1944 Part of Command-T is implemented in C as a Ruby extension for speed, allowing
1945 it to work responsively even on directory hierarchies containing enormous
1946 numbers of files. As such, a C compiler is required in order to build the
1947 extension and complete the installation.
1949 On Mac OS X, this can be obtained by installing the Xcode Tools that come on
1950 the Mac OS X install disc.
1952 On Windows, the RubyInstaller Development Kit can be used to conveniently
1953 install the necessary tool chain:
1955   http://rubyinstaller.org/downloads/archives
1957 At the time of writing, the appropriate development kit for use with Ruby
1958 1.8.7 is DevKit-3.4.5r3-20091110.
1960 To use the Development Kit extract the archive contents to your C:\Ruby
1961 folder.
1964 INSTALLATION                                    *command-t-installation*
1966 Command-T is distributed as a "vimball" which means that it can be installed
1967 by opening it in Vim and then sourcing it:
1969   :e command-t.vba
1970   :so %
1972 The files will be installed in your |'runtimepath'|. To check where this is
1973 you can issue:
1975   :echo &rtp
1977 The C extension must then be built, which can be done from the shell. If you
1978 use a typical |'runtimepath'| then the files were installed inside ~/.vim and
1979 you can build the extension with:
1981   cd ~/.vim/ruby/command-t
1982   ruby extconf.rb
1983   make
1985 Note: If you are an RVM user, you must perform the build using the same
1986 version of Ruby that Vim itself is linked against. This will often be the
1987 system Ruby, which can be selected before issuing the "make" command with:
1989   rvm use system
1992 MANAGING USING PATHOGEN                         *command-t-pathogen*
1994 Pathogen is a plugin that allows you to maintain plugin installations in
1995 separate, isolated subdirectories under the "bundle" directory in your
1996 |'runtimepath'|. The following examples assume that you already have
1997 Pathogen installed and configured, and that you are installing into
1998 ~/.vim/bundle. For more information about Pathogen, see:
2000   http://www.vim.org/scripts/script.php?script_id=2332
2002 If you manage your entire ~/.vim folder using Git then you can add the
2003 Command-T repository as a submodule:
2005   cd ~/.vim
2006   git submodule add git://git.wincent.com/command-t.git bundle/command-t
2007   git submodule init
2009 Or if you just wish to do a simple clone instead of using submodules:
2011   cd ~/.vim
2012   git clone git://git.wincent.com/command-t.git bundle/command-t
2014 Once you have a local copy of the repository you can update it at any time
2015 with:
2017   cd ~/.vim/bundle/command-t
2018   git pull
2020 Or you can switch to a specific release with:
2022   cd ~/.vim/bundle/command-t
2023   git checkout 0.8b
2025 After installing or updating you must build the extension:
2027   cd ~/.vim/bundle/command-t
2028   rake make
2030 While the Vimball installation automatically generates the help tags, under
2031 Pathogen it is necessary to do so explicitly from inside Vim:
2033   :call pathogen#helptags()
2036 TROUBLE-SHOOTING                                *command-t-trouble-shooting*
2038 Most installation problems are caused by a mismatch between the version of
2039 Ruby on the host operating system, and the version of Ruby that Vim itself
2040 linked against at compile time. For example, if one is 32-bit and the other is
2041 64-bit, or one is from the Ruby 1.9 series and the other is from the 1.8
2042 series, then the plug-in is not likely to work.
2044 As such, on Mac OS X, I recommend using the standard Ruby that comes with the
2045 system (currently 1.8.7) along with the latest version of MacVim (currently
2046 version 7.3). If you wish to use custom builds of Ruby or of MacVim (not
2047 recommmended) then you will have to take extra care to ensure that the exact
2048 same Ruby environment is in effect when building Ruby, Vim and the Command-T
2049 extension.
2051 For Windows, the following combination is known to work:
2053   - Vim 7.2 from http://www.vim.org/download.php:
2054       ftp://ftp.vim.org/pub/vim/pc/gvim72.exe
2055   - Ruby 1.8.7-p299 from http://rubyinstaller.org/downloads/archives:
2056       http://rubyforge.org/frs/download.php/71492/rubyinstaller-1.8.7-p299.exe
2057   - DevKit 3.4.5r3-20091110 from http://rubyinstaller.org/downloads/archives:
2058       http://rubyforge.org/frs/download.php/66888/devkit-3.4.5r3-20091110.7z
2060 If a problem occurs the first thing you should do is inspect the output of:
2062   ruby extconf.rb
2063   make
2065 During the installation, and:
2067   vim --version
2069 And compare the compilation and linker flags that were passed to the
2070 extension and to Vim itself when they were built. If the Ruby-related
2071 flags or architecture flags are different then it is likely that something
2072 has changed in your Ruby environment and the extension may not work until
2073 you eliminate the discrepancy.
2076 USAGE                                           *command-t-usage*
2078 Bring up the Command-T match window by typing:
2080   <Leader>t
2082 This mapping is set up automatically for you, provided you do not already have
2083 a mapping for <Leader>t or |:CommandT|. You can also bring up the match window
2084 by issuing the command:
2086   :CommandT
2088 A prompt will appear at the bottom of the screen along with a match window
2089 showing all of the files in the current directory (as returned by the
2090 |:pwd| command).
2092 For the most efficient file navigation within a project it's recommended that
2093 you |:cd| into the root directory of your project when starting to work on it.
2094 If you wish to open a file from outside of the project folder you can pass in
2095 an optional path argument (relative or absolute) to |:CommandT|:
2097   :CommandT ../path/to/other/files
2099 Type letters in the prompt to narrow down the selection, showing only the
2100 files whose paths contain those letters in the specified order. Letters do not
2101 need to appear consecutively in a path in order for it to be classified as a
2102 match.
2104 Once the desired file has been selected it can be opened by pressing <CR>.
2105 (By default files are opened in the current window, but there are other
2106 mappings that you can use to open in a vertical or horizontal split, or in
2107 a new tab.) Note that if you have |'nohidden'| set and there are unsaved
2108 changes in the current window when you press <CR> then opening in the current
2109 window would fail; in this case Command-T will open the file in a new split.
2111 The following mappings are active when the prompt has focus:
2113     <BS>        delete the character to the left of the cursor
2114     <Del>       delete the character at the cursor
2115     <Left>      move the cursor one character to the left
2116     <C-h>       move the cursor one character to the left
2117     <Right>     move the cursor one character to the right
2118     <C-l>       move the cursor one character to the right
2119     <C-a>       move the cursor to the start (left)
2120     <C-e>       move the cursor to the end (right)
2121     <C-u>       clear the contents of the prompt
2122     <Tab>       change focus to the match listing
2124 The following mappings are active when the match listing has focus:
2126     <Tab>       change focus to the prompt
2128 The following mappings are active when either the prompt or the match listing
2129 has focus:
2131     <CR>        open the selected file
2132     <C-CR>      open the selected file in a new split window
2133     <C-s>       open the selected file in a new split window
2134     <C-v>       open the selected file in a new vertical split window
2135     <C-t>       open the selected file in a new tab
2136     <C-j>       select next file in the match listing
2137     <C-n>       select next file in the match listing
2138     <Down>      select next file in the match listing
2139     <C-k>       select previous file in the match listing
2140     <C-p>       select previous file in the match listing
2141     <Up>        select previous file in the match listing
2142     <C-c>       cancel (dismisses match listing)
2144 The following is also available on terminals which support it:
2146     <Esc>       cancel (dismisses match listing)
2148 Note that the default mappings can be overriden by setting options in your
2149 ~/.vimrc file (see the OPTIONS section for a full list of available options).
2151 In addition, when the match listing has focus, typing a character will cause
2152 the selection to jump to the first path which begins with that character.
2153 Typing multiple characters consecutively can be used to distinguish between
2154 paths which begin with the same prefix.
2157 COMMANDS                                        *command-t-commands*
2159                                                 *:CommandT*
2160 |:CommandT|     Brings up the Command-T match window, starting in the
2161                 current working directory as returned by the|:pwd|
2162                 command.
2164                                                 *:CommandTFlush*
2165 |:CommandTFlush|Instructs the plug-in to flush its path cache, causing
2166                 the directory to be rescanned for new or deleted paths
2167                 the next time the match window is shown. In addition, all
2168                 configuration settings are re-evaluated, causing any
2169                 changes made to settings via the |:let| command to be picked
2170                 up.
2173 MAPPINGS                                        *command-t-mappings*
2175 By default Command-T comes with only one mapping:
2177   <Leader>t     bring up the Command-T match window
2179 However, Command-T won't overwrite a pre-existing mapping so if you prefer
2180 to define a different mapping use a line like this in your ~/.vimrc:
2182   nmap <silent> <Leader>t :CommandT<CR>
2184 Replacing "<Leader>t" with your mapping of choice.
2186 Note that in the case of MacVim you actually can map to Command-T (written
2187 as <D-t> in Vim) in your ~/.gvimrc file if you first unmap the existing menu
2188 binding of Command-T to "New Tab":
2190   if has("gui_macvim")
2191     macmenu &File.New\ Tab key=<nop>
2192     map <D-t> :CommandT<CR>
2193   endif
2195 When the Command-T window is active a number of other additional mappings
2196 become available for doing things like moving between and selecting matches.
2197 These are fully described above in the USAGE section, and settings for
2198 overriding the mappings are listed below under OPTIONS.
2201 OPTIONS                                         *command-t-options*
2203 A number of options may be set in your ~/.vimrc to influence the behaviour of
2204 the plug-in. To set an option, you include a line like this in your ~/.vimrc:
2206     let g:CommandTMaxFiles=20000
2208 To have Command-T pick up new settings immediately (that is, without having
2209 to restart Vim) you can issue the |:CommandTFlush| command after making
2210 changes via |:let|.
2212 Following is a list of all available options:
2214                                                 *g:CommandTMaxFiles*
2215   |g:CommandTMaxFiles|                           number (default 10000)
2217       The maximum number of files that will be considered when scanning the
2218       current directory. Upon reaching this number scanning stops.
2220                                                 *g:CommandTMaxDepth*
2221   |g:CommandTMaxDepth|                           number (default 15)
2223       The maximum depth (levels of recursion) to be explored when scanning the
2224       current directory. Any directories at levels beyond this depth will be
2225       skipped.
2227                                                 *g:CommandTMaxHeight*
2228   |g:CommandTMaxHeight|                          number (default: 0)
2230       The maximum height in lines the match window is allowed to expand to.
2231       If set to 0, the window will occupy as much of the available space as
2232       needed to show matching entries.
2234                                                 *g:CommandTAlwaysShowDotFiles*
2235   |g:CommandTAlwaysShowDotFiles|                 boolean (default: 0)
2237       By default Command-T will show dot-files only if the entered search
2238       string contains a dot that could cause a dot-file to match. When set to
2239       a non-zero value, this setting instructs Command-T to always include
2240       matching dot-files in the match list regardless of whether the search
2241       string contains a dot. See also |g:CommandTNeverShowDotFiles|.
2243                                                 *g:CommandTNeverShowDotFiles*
2244   |g:CommandTNeverShowDotFiles|                  boolean (default: 0)
2246       By default Command-T will show dot-files if the entered search string
2247       contains a dot that could cause a dot-file to match. When set to a
2248       non-zero value, this setting instructs Command-T to never show dot-files
2249       under any circumstances. Note that it is contradictory to set both this
2250       setting and |g:CommandTAlwaysShowDotFiles| to true, and if you do so Vim
2251       will suffer from headaches, nervous twitches, and sudden mood swings.
2253                                                 *g:CommandTScanDotDirectories*
2254   |g:CommandTScanDotDirectories|                 boolean (default: 0)
2256       Normally Command-T will not recurse into "dot-directories" (directories
2257       whose names begin with a dot) while performing its initial scan. Set
2258       this setting to a non-zero value to override this behavior and recurse.
2259       Note that this setting is completely independent of the
2260       |g:CommandTAlwaysShowDotFiles| and |g:CommandTNeverShowDotFiles|
2261       settings; those apply only to the selection and display of matches
2262       (after scanning has been performed), whereas
2263       |g:CommandTScanDotDirectories| affects the behaviour at scan-time.
2265       Note also that even with this setting on you can still use Command-T to
2266       open files inside a "dot-directory" such as ~/.vim, but you have to use
2267       the |:cd| command to change into that directory first. For example:
2269         :cd ~/.vim
2270         :CommandT
2272                                                 *g:CommandTMatchWindowAtTop*
2273   |g:CommandTMatchWindowAtTop|                   boolean (default: 0)
2275       When this settings is off (the default) the match window will appear at
2276       the bottom so as to keep it near to the prompt. Turning it on causes the
2277       match window to appear at the top instead. This may be preferable if you
2278       want the best match (usually the first one) to appear in a fixed location
2279       on the screen rather than moving as the number of matches changes during
2280       typing.
2282 As well as the basic options listed above, there are a number of settings that
2283 can be used to override the default key mappings used by Command-T. For
2284 example, to set <C-x> as the mapping for cancelling (dismissing) the Command-T
2285 window, you would add the following to your ~/.vimrc:
2287   let g:CommandTCancelMap='<C-x>'
2289 Multiple, alternative mappings may be specified using list syntax:
2291   let g:CommandTCancelMap=['<C-x>', '<C-c>']
2293 Following is a list of all map settings and their defaults:
2295                               Setting   Default mapping(s)
2297                                        *g:CommandTBackspaceMap*
2298               |g:CommandTBackspaceMap|  <BS>
2300                                        *g:CommandTDeleteMap*
2301                  |g:CommandTDeleteMap|  <Del>
2303                                        *g:CommandTAcceptSelectionMap*
2304         |g:CommandTAcceptSelectionMap|  <CR>
2306                                        *g:CommandTAcceptSelectionSplitMap*
2307    |g:CommandTAcceptSelectionSplitMap|  <C-CR>
2308                                         <C-s>
2310                                        *g:CommandTAcceptSelectionTabMap*
2311      |g:CommandTAcceptSelectionTabMap|  <C-t>
2313                                        *g:CommandTAcceptSelectionVSplitMap*
2314   |g:CommandTAcceptSelectionVSplitMap|  <C-v>
2316                                        *g:CommandTToggleFocusMap*
2317             |g:CommandTToggleFocusMap|  <Tab>
2319                                        *g:CommandTCancelMap*
2320                  |g:CommandTCancelMap|  <C-c>
2321                                         <Esc> (not on all terminals)
2323                                        *g:CommandTSelectNextMap*
2324              |g:CommandTSelectNextMap|  <C-n>
2325                                         <C-j>
2326                                         <Down>
2328                                        *g:CommandTSelectPrevMap*
2329              |g:CommandTSelectPrevMap|  <C-p>
2330                                         <C-k>
2331                                         <Up>
2333                                        *g:CommandTClearMap*
2334                   |g:CommandTClearMap|  <C-u>
2336                                        *g:CommandTCursorLeftMap*
2337              |g:CommandTCursorLeftMap|  <Left>
2338                                         <C-h>
2340                                        *g:CommandTCursorRightMap*
2341             |g:CommandTCursorRightMap|  <Right>
2342                                         <C-l>
2344                                        *g:CommandTCursorEndMap*
2345               |g:CommandTCursorEndMap|  <C-e>
2347                                        *g:CommandTCursorStartMap*
2348             |g:CommandTCursorStartMap|  <C-a>
2350 In addition to the options provided by Command-T itself, some of Vim's own
2351 settings can be used to control behavior:
2353                                                 *command-t-wildignore*
2354   |'wildignore'|                                 string (default: '')
2356       Vim's |'wildignore'| setting is used to determine which files should be
2357       excluded from listings. This is a comma-separated list of glob patterns.
2358       It defaults to the empty string, but common settings include "*.o,*.obj"
2359       (to exclude object files) or ".git,.svn" (to exclude SCM metadata
2360       directories). For example:
2362         :set wildignore+=*.o,*.obj,.git
2364       A pattern such as "vendor/rails/**" would exclude all files and
2365       subdirectories inside the "vendor/rails" directory (relative to
2366       directory Command-T starts in).
2368       See the |'wildignore'| documentation for more information.
2371 AUTHORS                                         *command-t-authors*
2373 Command-T is written and maintained by Wincent Colaiuta <win@wincent.com>.
2374 Other contributors that have submitted patches include (in alphabetical
2375 order):
2377   Lucas de Vries
2378   Mike Lundy
2379   Scott Bronson
2380   Sung Pae
2381   Zak Johnson
2383 As this was the first Vim plug-in I had ever written I was heavily influenced
2384 by the design of the LustyExplorer plug-in by Stephen Bach, which I understand
2385 is one of the largest Ruby-based Vim plug-ins to date.
2387 While the Command-T codebase doesn't contain any code directly copied from
2388 LustyExplorer, I did use it as a reference for answers to basic questions (like
2389 "How do you do 'X' in a Ruby-based Vim plug-in?"), and also copied some basic
2390 architectural decisions (like the division of the code into Prompt, Settings
2391 and MatchWindow classes).
2393 LustyExplorer is available from:
2395   http://www.vim.org/scripts/script.php?script_id=1890
2398 WEBSITE                                         *command-t-website*
2400 The official website for Command-T is:
2402   https://wincent.com/products/command-t
2404 The latest release will always be available from there.
2406 Development in progress can be inspected via the project's Git repository
2407 browser at:
2409   http://git.wincent.com/command-t.git
2411 A copy of each release is also available from the official Vim scripts site
2414   http://www.vim.org/scripts/script.php?script_id=3025
2416 Bug reports should be submitted to the issue tracker at:
2418   https://wincent.com/issues
2421 DONATIONS                                       *command-t-donations*
2423 Command-T itself is free software released under the terms of the BSD license.
2424 If you would like to support further development you can make a donation via
2425 PayPal to win@wincent.com:
2427   https://wincent.com/products/command-t/donations
2430 LICENSE                                         *command-t-license*
2432 Copyright 2010 Wincent Colaiuta. All rights reserved.
2434 Redistribution and use in source and binary forms, with or without
2435 modification, are permitted provided that the following conditions are met:
2437 1. Redistributions of source code must retain the above copyright notice,
2438    this list of conditions and the following disclaimer.
2439 2. Redistributions in binary form must reproduce the above copyright notice,
2440    this list of conditions and the following disclaimer in the documentation
2441    and/or other materials provided with the distribution.
2443 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2444 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2445 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2446 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
2447 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2448 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2449 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2450 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2451 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2452 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2453 POSSIBILITY OF SUCH DAMAGE.
2456 HISTORY                                         *command-t-history*
2458 0.8.1 (14 September 2010)
2460 - fix mapping issues for users who have set |'notimeout'| (patch from Sung
2461   Pae)
2463 0.8 (19 August 2010)
2465 - overrides for the default mappings can now be lists of strings, allowing
2466   multiple mappings to be defined for any given action
2467 - <Leader>t mapping only set up if no other map for |:CommandT| exists
2468   (patch from Scott Bronson)
2469 - prevent folds from appearing in the match listing
2470 - tweaks to avoid the likelihood of "Not enough room" errors when trying to
2471   open files
2472 - watch out for "nil" windows when restoring window dimensions
2473 - optimizations (avoid some repeated downcasing)
2474 - move all Ruby files under the "command-t" subdirectory and avoid polluting
2475   the "Vim" module namespace
2477 0.8b (11 July 2010)
2479 - large overhaul of the scoring algorithm to make the ordering of returned
2480   results more intuitive; given the scope of the changes and room for
2481   optimization of the new algorithm, this release is labelled as "beta"
2483 0.7 (10 June 2010)
2485 - handle more |'wildignore'| patterns by delegating to Vim's own |expand()|
2486   function; with this change it is now viable to exclude patterns such as
2487   'vendor/rails/**' in addition to filename-only patterns like '*.o' and
2488   '.git' (patch from Mike Lundy)
2489 - always sort results alphabetically for empty search strings; this eliminates
2490   filesystem-specific variations (patch from Mike Lundy)
2492 0.6 (28 April 2010)
2494 - |:CommandT| now accepts an optional parameter to specify the starting
2495   directory, temporarily overriding the usual default of Vim's |:pwd|
2496 - fix truncated paths when operating from root directory
2498 0.5.1 (11 April 2010)
2500 - fix for Ruby 1.9 compatibility regression introduced in 0.5
2501 - documentation enhancements, specifically targetted at Windows users
2503 0.5 (3 April 2010)
2505 - |:CommandTFlush| now re-evaluates settings, allowing changes made via |let|
2506   to be picked up without having to restart Vim
2507 - fix premature abort when scanning very deep directory hierarchies
2508 - remove broken |<Esc>| key mapping on vt100 and xterm terminals
2509 - provide settings for overriding default mappings
2510 - minor performance optimization
2512 0.4 (27 March 2010)
2514 - add |g:CommandTMatchWindowAtTop| setting (patch from Zak Johnson)
2515 - documentation fixes and enhancements
2516 - internal refactoring and simplification
2518 0.3 (24 March 2010)
2520 - add |g:CommandTMaxHeight| setting for controlling the maximum height of the
2521   match window (patch from Lucas de Vries)
2522 - fix bug where |'list'| setting might be inappropriately set after dismissing
2523   Command-T
2524 - compatibility fix for different behaviour of "autoload" under Ruby 1.9.1
2525 - avoid "highlight group not found" warning when run under a version of Vim
2526   that does not have syntax highlighting support
2527 - open in split when opening normally would fail due to |'hidden'| and
2528   |'modified'| values
2530 0.2 (23 March 2010)
2532 - compatibility fixes for compilation under Ruby 1.9 series
2533 - compatibility fixes for compilation under Ruby 1.8.5
2534 - compatibility fixes for Windows and other non-UNIX platforms
2535 - suppress "mapping already exists" message if <Leader>t mapping is already
2536   defined when plug-in is loaded
2537 - exclude paths based on |'wildignore'| setting rather than a hardcoded
2538   regular expression
2540 0.1 (22 March 2010)
2542 - initial public release
2544 ------------------------------------------------------------------------------
2545 vim:tw=78:ft=help:
2546 plugin/command-t.vim    [[[1
2548 " command-t.vim
2549 " Copyright 2010 Wincent Colaiuta. All rights reserved.
2551 " Redistribution and use in source and binary forms, with or without
2552 " modification, are permitted provided that the following conditions are met:
2554 " 1. Redistributions of source code must retain the above copyright notice,
2555 "    this list of conditions and the following disclaimer.
2556 " 2. Redistributions in binary form must reproduce the above copyright notice,
2557 "    this list of conditions and the following disclaimer in the documentation
2558 "    and/or other materials provided with the distribution.
2560 " THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2561 " AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2562 " IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2563 " ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
2564 " LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2565 " CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2566 " SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2567 " INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2568 " CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2569 " ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2570 " POSSIBILITY OF SUCH DAMAGE.
2572 if exists("g:command_t_loaded")
2573   finish
2574 endif
2575 let g:command_t_loaded = 1
2577 command -nargs=? -complete=dir CommandT call <SID>CommandTShow(<q-args>)
2578 command CommandTFlush call <SID>CommandTFlush()
2580 if !hasmapto('CommandT')
2581   silent! nmap <unique> <silent> <Leader>t :CommandT<CR>
2582 endif
2584 function s:CommandTRubyWarning()
2585   echohl WarningMsg
2586   echo "command-t.vim requires Vim to be compiled with Ruby support"
2587   echo "For more information type:  :help command-t"
2588   echohl none
2589 endfunction
2591 function s:CommandTShow(arg)
2592   if has('ruby')
2593     ruby $command_t.show
2594   else
2595     call s:CommandTRubyWarning()
2596   endif
2597 endfunction
2599 function s:CommandTFlush()
2600   if has('ruby')
2601     ruby $command_t.flush
2602   else
2603     call s:CommandTRubyWarning()
2604   endif
2605 endfunction
2607 if !has('ruby')
2608   finish
2609 endif
2611 function CommandTHandleKey(arg)
2612   ruby $command_t.handle_key
2613 endfunction
2615 function CommandTBackspace()
2616   ruby $command_t.backspace
2617 endfunction
2619 function CommandTDelete()
2620   ruby $command_t.delete
2621 endfunction
2623 function CommandTAcceptSelection()
2624   ruby $command_t.accept_selection
2625 endfunction
2627 function CommandTAcceptSelectionTab()
2628   ruby $command_t.accept_selection :command => 'tabe'
2629 endfunction
2631 function CommandTAcceptSelectionSplit()
2632   ruby $command_t.accept_selection :command => 'sp'
2633 endfunction
2635 function CommandTAcceptSelectionVSplit()
2636   ruby $command_t.accept_selection :command => 'vs'
2637 endfunction
2639 function CommandTToggleFocus()
2640   ruby $command_t.toggle_focus
2641 endfunction
2643 function CommandTCancel()
2644   ruby $command_t.cancel
2645 endfunction
2647 function CommandTSelectNext()
2648   ruby $command_t.select_next
2649 endfunction
2651 function CommandTSelectPrev()
2652   ruby $command_t.select_prev
2653 endfunction
2655 function CommandTClear()
2656   ruby $command_t.clear
2657 endfunction
2659 function CommandTCursorLeft()
2660   ruby $command_t.cursor_left
2661 endfunction
2663 function CommandTCursorRight()
2664   ruby $command_t.cursor_right
2665 endfunction
2667 function CommandTCursorEnd()
2668   ruby $command_t.cursor_end
2669 endfunction
2671 function CommandTCursorStart()
2672   ruby $command_t.cursor_start
2673 endfunction
2675 ruby << EOF
2676   # require Ruby files
2677   begin
2678     # prepare controller
2679     require 'command-t/vim'
2680     require 'command-t/controller'
2681     $command_t = CommandT::Controller.new
2682   rescue LoadError
2683     load_path_modified = false
2684     ::VIM::evaluate('&runtimepath').to_s.split(',').each do |path|
2685       lib = "#{path}/ruby"
2686       if !$LOAD_PATH.include?(lib) and File.exist?(lib)
2687         $LOAD_PATH << lib
2688         load_path_modified = true
2689       end
2690     end
2691     retry if load_path_modified
2693     # could get here if C extension was not compiled, or was compiled
2694     # for the wrong architecture or Ruby version
2695     require 'command-t/stub'
2696     $command_t = CommandT::Stub.new
2697   end