Skip to content

kuting/PTPasscodeViewController

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 

Repository files navigation

" Vimball Archiver by Charles E. Campbell, Jr., Ph.D. UseVimball finish ruby/command-t/controller.rb [[[1 373

Copyright 2010-2013 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'command-t/finder/buffer_finder' require 'command-t/finder/jump_finder' require 'command-t/finder/file_finder' require 'command-t/finder/tag_finder' require 'command-t/match_window' require 'command-t/prompt' require 'command-t/vim/path_utilities'

module CommandT class Controller include VIM::PathUtilities

def initialize
  @prompt = Prompt.new
end

def show_buffer_finder
  @path          = VIM::pwd
  @active_finder = buffer_finder
  show
end

def show_jump_finder
  @path          = VIM::pwd
  @active_finder = jump_finder
  show
end

def show_tag_finder
  @path          = VIM::pwd
  @active_finder = tag_finder
  show
end

def show_file_finder
  # optional parameter will be desired starting directory, or ""
  @path             = File.expand_path(::VIM::evaluate('a:arg'), VIM::pwd)
  @active_finder    = file_finder
  file_finder.path  = @path
  show
rescue Errno::ENOENT
  # probably a problem with the optional parameter
  @match_window.print_no_such_file_or_directory
end

def hide
  @match_window.close
  if VIM::Window.select @initial_window
    if @initial_buffer.number == 0
      # upstream bug: buffer number misreported as 0
      # see: https://wincent.com/issues/1617
      ::VIM::command "silent b #{@initial_buffer.name}"
    else
      ::VIM::command "silent b #{@initial_buffer.number}"
    end
  end
end

# Take current matches and stick them in the quickfix window.
def quickfix
  hide

  matches = @matches.map do |match|
    "{ 'filename': '#{VIM::escape_for_single_quotes match}' }"
  end.join(', ')

  ::VIM::command 'call setqflist([' + matches + '])'
  ::VIM::command 'cope'
end

def refresh
  return unless @active_finder && @active_finder.respond_to?(:flush)
  @active_finder.flush
  list_matches
end

def flush
  @max_height   = nil
  @min_height   = nil
  @file_finder  = nil
  @tag_finder   = nil
end

def handle_key
  key = ::VIM::evaluate('a:arg').to_i.chr
  if @focus == @prompt
    @prompt.add! key
    list_matches
  else
    @match_window.find key
  end
end

def backspace
  if @focus == @prompt
    @prompt.backspace!
    list_matches
  end
end

def delete
  if @focus == @prompt
    @prompt.delete!
    list_matches
  end
end

def accept_selection options = {}
  selection = @match_window.selection
  hide
  open_selection(selection, options) unless selection.nil?
end

def toggle_focus
  @focus.unfocus # old focus
  @focus = @focus == @prompt ? @match_window : @prompt
  @focus.focus # new focus
end

def cancel
  hide
end

def select_next
  @match_window.select_next
end

def select_prev
  @match_window.select_prev
end

def clear
  @prompt.clear!
  list_matches
end

def cursor_left
  @prompt.cursor_left if @focus == @prompt
end

def cursor_right
  @prompt.cursor_right if @focus == @prompt
end

def cursor_end
  @prompt.cursor_end if @focus == @prompt
end

def cursor_start
  @prompt.cursor_start if @focus == @prompt
end

def leave
  @match_window.leave
end

def unload
  @match_window.unload
end

private

def show
  @initial_window   = $curwin
  @initial_buffer   = $curbuf
  @match_window     = MatchWindow.new \
    :highlight_color      => get_string('g:CommandTHighlightColor'),
    :match_window_at_top  => get_bool('g:CommandTMatchWindowAtTop'),
    :match_window_reverse => get_bool('g:CommandTMatchWindowReverse'),
    :min_height           => min_height,
    :prompt               => @prompt
  @focus            = @prompt
  @prompt.focus
  register_for_key_presses
  clear # clears prompt and lists matches
end

def max_height
  @max_height ||= get_number('g:CommandTMaxHeight') || 0
end

def min_height
  @min_height ||= begin
    min_height = get_number('g:CommandTMinHeight') || 0
    min_height = max_height if max_height != 0 && min_height > max_height
    min_height
  end
end

def get_number name
  VIM::exists?(name) ? ::VIM::evaluate("#{name}").to_i : nil
end

def get_bool name
  VIM::exists?(name) ? ::VIM::evaluate("#{name}").to_i != 0 : nil
end

def get_string name
  VIM::exists?(name) ? ::VIM::evaluate("#{name}").to_s : nil
end

# expect a string or a list of strings
def get_list_or_string name
  return nil unless VIM::exists?(name)
  list_or_string = ::VIM::evaluate("#{name}")
  if list_or_string.kind_of?(Array)
    list_or_string.map { |item| item.to_s }
  else
    list_or_string.to_s
  end
end

# Backslash-escape space, \, |, %, #, "
def sanitize_path_string str
  # for details on escaping command-line mode arguments see: :h :
  # (that is, help on ":") in the Vim documentation.
  str.gsub(/[ \\|%#"]/, '\\\\\0')
end

def default_open_command
  if !get_bool('&hidden') && get_bool('&modified')
    'sp'
  else
    'e'
  end
end

def ensure_appropriate_window_selection
  # normally we try to open the selection in the current window, but there
  # is one exception:
  #
  # - we don't touch any "unlisted" buffer with buftype "nofile" (such as
  #   NERDTree or MiniBufExplorer); this is to avoid things like the "Not
  #   enough room" error which occurs when trying to open in a split in a
  #   shallow (potentially 1-line) buffer like MiniBufExplorer is current
  #
  # Other "unlisted" buffers, such as those with buftype "help" are treated
  # normally.
  initial = $curwin
  while true do
    break unless ::VIM::evaluate('&buflisted').to_i == 0 &&
      ::VIM::evaluate('&buftype').to_s == 'nofile'
    ::VIM::command 'wincmd w'     # try next window
    break if $curwin == initial # have already tried all
  end
end

def open_selection selection, options = {}
  command = options[:command] || default_open_command
  selection = File.expand_path selection, @path
  selection = relative_path_under_working_directory selection
  selection = sanitize_path_string selection
  selection = File.join('.', selection) if selection =~ /^\+/
  ensure_appropriate_window_selection

  @active_finder.open_selection command, selection, options
end

def map key, function, param = nil
  ::VIM::command "noremap <silent> <buffer> #{key} " \
    ":call CommandT#{function}(#{param})<CR>"
end

def term
  @term ||= ::VIM::evaluate('&term')
end

def register_for_key_presses
  # "normal" keys (interpreted literally)
  numbers     = ('0'..'9').to_a.join
  lowercase   = ('a'..'z').to_a.join
  uppercase   = lowercase.upcase
  punctuation = '<>`@#~!"$%&/()=+*-_.,;:?\\\'{}[] ' # and space
  (numbers + lowercase + uppercase + punctuation).each_byte do |b|
    map "<Char-#{b}>", 'HandleKey', b
  end

  # "special" keys (overridable by settings)
  {
    'AcceptSelection'       => '<CR>',
    'AcceptSelectionSplit'  => ['<C-CR>', '<C-s>'],
    'AcceptSelectionTab'    => '<C-t>',
    'AcceptSelectionVSplit' => '<C-v>',
    'Backspace'             => '<BS>',
    'Cancel'                => ['<C-c>', '<Esc>'],
    'Clear'                 => '<C-u>',
    'CursorEnd'             => '<C-e>',
    'CursorLeft'            => ['<Left>', '<C-h>'],
    'CursorRight'           => ['<Right>', '<C-l>'],
    'CursorStart'           => '<C-a>',
    'Delete'                => '<Del>',
    'Quickfix'              => '<C-q>',
    'Refresh'               => '<C-f>',
    'SelectNext'            => ['<C-n>', '<C-j>', '<Down>'],
    'SelectPrev'            => ['<C-p>', '<C-k>', '<Up>'],
    'ToggleFocus'           => '<Tab>',
  }.each do |key, value|
    if override = get_list_or_string("g:CommandT#{key}Map")
      Array(override).each do |mapping|
        map mapping, key
      end
    else
      Array(value).each do |mapping|
        unless mapping == '<Esc>' && term =~ /\A(screen|xterm|vt100)/
          map mapping, key
        end
      end
    end
  end
end

# Returns the desired maximum number of matches, based on available
# vertical space and the g:CommandTMaxHeight option.
def match_limit
  limit = VIM::Screen.lines - 5
  limit = 1 if limit < 0
  limit = [limit, max_height].min if max_height > 0
  limit
end

def list_matches
  @matches = @active_finder.sorted_matches_for @prompt.abbrev, :limit => match_limit
  @match_window.matches = @matches
end

def buffer_finder
  @buffer_finder ||= CommandT::BufferFinder.new
end

def file_finder
  @file_finder ||= CommandT::FileFinder.new nil,
    :max_depth              => get_number('g:CommandTMaxDepth'),
    :max_files              => get_number('g:CommandTMaxFiles'),
    :max_caches             => get_number('g:CommandTMaxCachedDirectories'),
    :always_show_dot_files  => get_bool('g:CommandTAlwaysShowDotFiles'),
    :never_show_dot_files   => get_bool('g:CommandTNeverShowDotFiles'),
    :scan_dot_directories   => get_bool('g:CommandTScanDotDirectories'),
    :wild_ignore            => get_string('g:CommandTWildIgnore')
end

def jump_finder
  @jump_finder ||= CommandT::JumpFinder.new
end

def tag_finder
  @tag_finder ||= CommandT::TagFinder.new \
    :include_filenames => get_bool('g:CommandTTagIncludeFilenames')
end

end # class Controller end # module commandT ruby/command-t/extconf.rb [[[1 34

Copyright 2010 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'mkmf'

def missing item puts "couldn't find #{item} (required)" exit 1 end

RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']

have_header('ruby.h') or missing('ruby.h') create_makefile('ext') ruby/command-t/finder/buffer_finder.rb [[[1 35

Copyright 2010-2011 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'command-t/ext' # CommandT::Matcher require 'command-t/scanner/buffer_scanner' require 'command-t/finder'

module CommandT class BufferFinder < Finder def initialize @scanner = BufferScanner.new @matcher = Matcher.new @scanner, :always_show_dot_files => true end end # class BufferFinder end # CommandT ruby/command-t/finder/file_finder.rb [[[1 39

Copyright 2010-2012 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'command-t/ext' # CommandT::Matcher require 'command-t/finder' require 'command-t/scanner/file_scanner'

module CommandT class FileFinder < Finder def initialize path = Dir.pwd, options = {} @scanner = FileScanner.new path, options @matcher = Matcher.new @scanner, options end

def flush
  @scanner.flush
end

end # class FileFinder end # CommandT ruby/command-t/finder/jump_finder.rb [[[1 35

Copyright 2011 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'command-t/ext' # CommandT::Matcher require 'command-t/scanner/jump_scanner' require 'command-t/finder'

module CommandT class JumpFinder < Finder def initialize @scanner = JumpScanner.new @matcher = Matcher.new @scanner, :always_show_dot_files => true end end # class JumpFinder end # module CommandT ruby/command-t/finder/tag_finder.rb [[[1 44

Copyright 2011-2012 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'command-t/ext' # CommandT::Matcher require 'command-t/scanner/tag_scanner' require 'command-t/finder'

module CommandT class TagFinder < Finder def initialize options = {} @scanner = TagScanner.new options @matcher = Matcher.new @scanner, :always_show_dot_files => true end

def open_selection command, selection, options = {}
  if @scanner.include_filenames
    selection = selection[0, selection.index(':')]
  end

  #  open the tag and center the screen on it
  ::VIM::command "silent! tag #{selection} | :normal zz"
end

end # class TagFinder end # module CommandT ruby/command-t/finder.rb [[[1 54

Copyright 2010-2012 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'command-t/ext' # CommandT::Matcher

module CommandT

Encapsulates a Scanner instance (which builds up a list of available files

in a directory) and a Matcher instance (which selects from that list based

on a search string).

Specialized subclasses use different kinds of scanners adapted for

different kinds of search (files, buffers).

class Finder include VIM::PathUtilities

def initialize path = Dir.pwd, options = {}
  raise RuntimeError, 'Subclass responsibility'
end

# Options:
#   :limit (integer): limit the number of returned matches
def sorted_matches_for str, options = {}
  @matcher.sorted_matches_for str, options
end

def open_selection command, selection, options = {}
  ::VIM::command "silent #{command} #{selection}"
end

def path= path
  @scanner.path = path
end

end # class Finder end # CommandT ruby/command-t/match_window.rb [[[1 446

Copyright 2010-2013 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'ostruct' require 'command-t/settings'

module CommandT class MatchWindow SELECTION_MARKER = '> ' MARKER_LENGTH = SELECTION_MARKER.length UNSELECTED_MARKER = ' ' * MARKER_LENGTH MH_START = '' MH_END = '' @@buffer = nil

def initialize options = {}
  @highlight_color = options[:highlight_color] || 'PmenuSel'
  @min_height      = options[:min_height]
  @prompt          = options[:prompt]
  @reverse_list    = options[:match_window_reverse]

  # save existing window dimensions so we can restore them later
  @windows = []
  (0..(::VIM::Window.count - 1)).each do |i|
    @windows << OpenStruct.new(:index   => i,
                               :height  => ::VIM::Window[i].height,
                               :width   => ::VIM::Window[i].width)
  end

  # global settings (must manually save and restore)
  @settings = Settings.new
  ::VIM::set_option 'timeout'         # ensure mappings timeout
  ::VIM::set_option 'timeoutlen=0'    # respond immediately to mappings
  ::VIM::set_option 'nohlsearch'      # don't highlight search strings
  ::VIM::set_option 'noinsertmode'    # don't make Insert mode the default
  ::VIM::set_option 'noshowcmd'       # don't show command info on last line
  ::VIM::set_option 'report=9999'     # don't show "X lines changed" reports
  ::VIM::set_option 'sidescroll=0'    # don't sidescroll in jumps
  ::VIM::set_option 'sidescrolloff=0' # don't sidescroll automatically
  ::VIM::set_option 'noequalalways'   # don't auto-balance window sizes

  # show match window
  split_location = options[:match_window_at_top] ? 'topleft' : 'botright'
  if @@buffer # still have buffer from last time
    ::VIM::command "silent! #{split_location} #{@@buffer.number}sbuffer"
    raise "Can't re-open GoToFile buffer" unless $curbuf.number == @@buffer.number
    $curwin.height = 1
  else        # creating match window for first time and set it up
    split_command = "silent! #{split_location} 1split GoToFile"
    [
      split_command,
      'setlocal bufhidden=unload',  # unload buf when no longer displayed
      'setlocal buftype=nofile',    # buffer is not related to any file
      'setlocal nomodifiable',      # prevent manual edits
      'setlocal noswapfile',        # don't create a swapfile
      'setlocal nowrap',            # don't soft-wrap
      'setlocal nonumber',          # don't show line numbers
      'setlocal nolist',            # don't use List mode (visible tabs etc)
      'setlocal foldcolumn=0',      # don't show a fold column at side
      'setlocal foldlevel=99',      # don't fold anything
      'setlocal nocursorline',      # don't highlight line cursor is on
      'setlocal nospell',           # spell-checking off
      'setlocal nobuflisted',       # don't show up in the buffer list
      'setlocal textwidth=0'        # don't hard-wrap (break long lines)
    ].each { |command| ::VIM::command command }

    # don't show the color column
    ::VIM::command 'setlocal colorcolumn=0' if VIM::exists?('+colorcolumn')

    # don't show relative line numbers
    ::VIM::command 'setlocal norelativenumber' if VIM::exists?('+relativenumber')

    # sanity check: make sure the buffer really was created
    raise "Can't find GoToFile buffer" unless $curbuf.name.match /GoToFile\z/
    @@buffer = $curbuf
  end

  # syntax coloring
  if VIM::has_syntax?
    ::VIM::command "syntax match CommandTSelection \"^#{SELECTION_MARKER}.\\+$\""
    ::VIM::command 'syntax match CommandTNoEntries "^-- NO MATCHES --$"'
    ::VIM::command 'syntax match CommandTNoEntries "^-- NO SUCH FILE OR DIRECTORY --$"'
    ::VIM::command 'setlocal synmaxcol=9999'

    if VIM::has_conceal?
      ::VIM::command 'setlocal conceallevel=2'
      ::VIM::command 'setlocal concealcursor=nvic'
      ::VIM::command 'syntax region CommandTCharMatched ' \
                     "matchgroup=CommandTCharMatched start=+#{MH_START}+ " \
                     "matchgroup=CommandTCharMatchedEnd end=+#{MH_END}+ concealends"
      ::VIM::command 'highlight def CommandTCharMatched ' \
                     'term=bold,underline cterm=bold,underline ' \
                     'gui=bold,underline'
    end

    ::VIM::command "highlight link CommandTSelection #{@highlight_color}"
    ::VIM::command 'highlight link CommandTNoEntries Error'
    ::VIM::evaluate 'clearmatches()'

    # hide cursor
    @cursor_highlight = get_cursor_highlight
    hide_cursor
  end

  # perform cleanup using an autocmd to ensure we don't get caught out
  # by some unexpected means of dismissing or leaving the Command-T window
  # (eg. <C-W q>, <C-W k> etc)
  ::VIM::command 'autocmd! * <buffer>'
  ::VIM::command 'autocmd BufLeave <buffer> silent! ruby $command_t.leave'
  ::VIM::command 'autocmd BufUnload <buffer> silent! ruby $command_t.unload'

  @has_focus  = false
  @selection  = nil
  @abbrev     = ''
  @window     = $curwin
end

def close
  # Unlisted buffers like those provided by Netrw, NERDTree and Vim's help
  # don't actually appear in the buffer list; if they are the only such
  # buffers present when Command-T is invoked (for example, when invoked
  # immediately after starting Vim with a directory argument, like `vim .`)
  # then performing the normal clean-up will yield an "E90: Cannot unload
  # last buffer" error. We can work around that by doing a :quit first.
  if ::VIM::Buffer.count == 0
    ::VIM::command 'silent quit'
  end

  # Workaround for upstream bug in Vim 7.3 on some platforms
  #
  # On some platforms, $curbuf.number always returns 0. One workaround is
  # to build Vim with --disable-largefile, but as this is producing lots of
  # support requests, implement the following fallback to the buffer name
  # instead, at least until upstream gets fixed.
  #
  # For more details, see: https://wincent.com/issues/1617
  if $curbuf.number == 0
    # use bwipeout as bunload fails if passed the name of a hidden buffer
    ::VIM::command 'silent! bwipeout! GoToFile'
    @@buffer = nil
  else
    ::VIM::command "silent! bunload! #{@@buffer.number}"
  end
end

def leave
  close
  unload
end

def unload
  restore_window_dimensions
  @settings.restore
  @prompt.dispose
  show_cursor
end

def add! char
  @abbrev += char
end

def backspace!
  @abbrev.chop!
end

def select_next
  if @selection < @matches.length - 1
    @selection += 1
    print_match(@selection - 1) # redraw old selection (removes marker)
    print_match(@selection)     # redraw new selection (adds marker)
    move_cursor_to_selected_line
  else
    # (possibly) loop or scroll
  end
end

def select_prev
  if @selection > 0
    @selection -= 1
    print_match(@selection + 1) # redraw old selection (removes marker)
    print_match(@selection)     # redraw new selection (adds marker)
    move_cursor_to_selected_line
  else
    # (possibly) loop or scroll
  end
end

def matches= matches
  matches = matches.reverse if @reverse_list
  if matches != @matches
    @matches = matches
    @selection = @reverse_list ? @matches.length - 1 : 0
    print_matches
    move_cursor_to_selected_line
  end
end

def focus
  unless @has_focus
    @has_focus = true
    if VIM::has_syntax?
      ::VIM::command 'highlight link CommandTSelection Search'
    end
  end
end

def unfocus
  if @has_focus
    @has_focus = false
    if VIM::has_syntax?
      ::VIM::command "highlight link CommandTSelection #{@highlight_color}"
    end
  end
end

def find char
  # is this a new search or the continuation of a previous one?
  now = Time.now
  if @last_key_time.nil? or @last_key_time < (now - 0.5)
    @find_string = char
  else
    @find_string += char
  end
  @last_key_time = now

  # see if there's anything up ahead that matches
  @matches.each_with_index do |match, idx|
    if match[0, @find_string.length].casecmp(@find_string) == 0
      old_selection = @selection
      @selection = idx
      print_match(old_selection)  # redraw old selection (removes marker)
      print_match(@selection)     # redraw new selection (adds marker)
      break
    end
  end
end

# Returns the currently selected item as a String.
def selection
  @matches[@selection]
end

def print_no_such_file_or_directory
  print_error 'NO SUCH FILE OR DIRECTORY'
end

private

def move_cursor_to_selected_line
  # on some non-GUI terminals, the cursor doesn't hide properly
  # so we move the cursor to prevent it from blinking away in the
  # upper-left corner in a distracting fashion
  @window.cursor = [@selection + 1, 0]
end

def print_error msg
  return unless VIM::Window.select(@window)
  unlock
  clear
  @window.height = @min_height > 0 ? @min_height : 1
  @@buffer[1] = "-- #{msg} --"
  lock
end

def restore_window_dimensions
  # sort from tallest to shortest, tie-breaking on window width
  @windows.sort! do |a, b|
    order = b.height <=> a.height
    if order.zero?
      b.width <=> a.width
    else
      order
    end
  end

  # starting with the tallest ensures that there are no constraints
  # preventing windows on the side of vertical splits from regaining
  # their original full size
  @windows.each do |w|
    # beware: window may be nil
    if window = ::VIM::Window[w.index]
      window.height = w.height
      window.width  = w.width
    end
  end
end

def match_text_for_idx idx
  match = truncated_match @matches[idx].to_s
  if idx == @selection
    prefix = SELECTION_MARKER
    suffix = padding_for_selected_match match
  else
    if VIM::has_syntax? && VIM::has_conceal?
      match = match_with_syntax_highlight match
    end
    prefix = UNSELECTED_MARKER
    suffix = ''
  end
  prefix + match + suffix
end

# Highlight matching characters within the matched string.
#
# Note that this is only approximate; it will highlight the first matching
# instances within the string, which may not actually be the instances that
# were used by the matching/scoring algorithm to determine the best score
# for the match.
#
def match_with_syntax_highlight match
  highlight_chars = @prompt.abbrev.downcase.chars.to_a
  match.chars.inject([]) do |output, char|
    if char.downcase == highlight_chars.first
      highlight_chars.shift
      output.concat [MH_START, char, MH_END]
    else
      output << char
    end
  end.join
end

# Print just the specified match.
def print_match idx
  return unless VIM::Window.select(@window)
  unlock
  @@buffer[idx + 1] = match_text_for_idx idx
  lock
end

# Print all matches.
def print_matches
  match_count = @matches.length
  if match_count == 0
    print_error 'NO MATCHES'
  else
    return unless VIM::Window.select(@window)
    unlock
    clear
    actual_lines = 1
    @window_width = @window.width # update cached value
    max_lines = VIM::Screen.lines - 5
    max_lines = 1 if max_lines < 0
    actual_lines = match_count < @min_height ? @min_height : match_count
    actual_lines = max_lines if actual_lines > max_lines
    @window.height = actual_lines
    (1..actual_lines).each do |line|
      idx = line - 1
      if @@buffer.count >= line
        @@buffer[line] = match_text_for_idx idx
      else
        @@buffer.append line - 1, match_text_for_idx(idx)
      end
    end
    lock
  end
end

# Prepare padding for match text (trailing spaces) so that selection
# highlighting extends all the way to the right edge of the window.
def padding_for_selected_match str
  len = str.length
  if len >= @window_width - MARKER_LENGTH
    ''
  else
    ' ' * (@window_width - MARKER_LENGTH - len)
  end
end

# Convert "really/long/path" into "really...path" based on available
# window width.
def truncated_match str
  len = str.length
  available_width = @window_width - MARKER_LENGTH
  return str if len <= available_width
  left = (available_width / 2) - 1
  right = (available_width / 2) - 2 + (available_width % 2)
  str[0, left] + '...' + str[-right, right]
end

def clear
  # range = % (whole buffer)
  # action = d (delete)
  # register = _ (black hole register, don't record deleted text)
  ::VIM::command 'silent %d _'
end

def get_cursor_highlight
  # there are 3 possible formats to check for, each needing to be
  # transformed in a certain way in order to reapply the highlight:
  #   Cursor xxx guifg=bg guibg=fg      -> :hi! Cursor guifg=bg guibg=fg
  #   Cursor xxx links to SomethingElse -> :hi! link Cursor SomethingElse
  #   Cursor xxx cleared                -> :hi! clear Cursor
  highlight = VIM::capture 'silent! 0verbose highlight Cursor'

  if highlight =~ /^Cursor\s+xxx\s+links to (\w+)/
    "link Cursor #{$~[1]}"
  elsif highlight =~ /^Cursor\s+xxx\s+cleared/
    'clear Cursor'
  elsif highlight =~ /Cursor\s+xxx\s+(.+)/
    "Cursor #{$~[1]}"
  else # likely cause E411 Cursor highlight group not found
    nil
  end
end

def hide_cursor
  if @cursor_highlight
    ::VIM::command 'highlight Cursor NONE'
  end
end

def show_cursor
  if @cursor_highlight
    ::VIM::command "highlight #{@cursor_highlight}"
  end
end

def lock
  ::VIM::command 'setlocal nomodifiable'
end

def unlock
  ::VIM::command 'setlocal modifiable'
end

end end ruby/command-t/prompt.rb [[[1 165

Copyright 2010 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

module CommandT

Abuse the status line as a prompt.

class Prompt attr_accessor :abbrev

def initialize
  @abbrev     = ''  # abbreviation entered so far
  @col        = 0   # cursor position
  @has_focus  = false
end

# Erase whatever is displayed in the prompt line,
# effectively disposing of the prompt
def dispose
  ::VIM::command 'echo'
  ::VIM::command 'redraw'
end

# Clear any entered text.
def clear!
  @abbrev = ''
  @col    = 0
  redraw
end

# Insert a character at (before) the current cursor position.
def add! char
  left, cursor, right = abbrev_segments
  @abbrev = left + char + cursor + right
  @col += 1
  redraw
end

# Delete a character to the left of the current cursor position.
def backspace!
  if @col > 0
    left, cursor, right = abbrev_segments
    @abbrev = left.chop! + cursor + right
    @col -= 1
    redraw
  end
end

# Delete a character at the current cursor position.
def delete!
  if @col < @abbrev.length
    left, cursor, right = abbrev_segments
    @abbrev = left + right
    redraw
  end
end

def cursor_left
  if @col > 0
    @col -= 1
    redraw
  end
end

def cursor_right
  if @col < @abbrev.length
    @col += 1
    redraw
  end
end

def cursor_end
  if @col < @abbrev.length
    @col = @abbrev.length
    redraw
  end
end

def cursor_start
  if @col != 0
    @col = 0
    redraw
  end
end

def redraw
  if @has_focus
    prompt_highlight = 'Comment'
    normal_highlight = 'None'
    cursor_highlight = 'Underlined'
  else
    prompt_highlight = 'NonText'
    normal_highlight = 'NonText'
    cursor_highlight = 'NonText'
  end
  left, cursor, right = abbrev_segments
  components = [prompt_highlight, '>>', 'None', ' ']
  components += [normal_highlight, left] unless left.empty?
  components += [cursor_highlight, cursor] unless cursor.empty?
  components += [normal_highlight, right] unless right.empty?
  components += [cursor_highlight, ' '] if cursor.empty?
  set_status *components
end

def focus
  unless @has_focus
    @has_focus = true
    redraw
  end
end

def unfocus
  if @has_focus
    @has_focus = false
    redraw
  end
end

private

# Returns the @abbrev string divided up into three sections, any of
# which may actually be zero width, depending on the location of the
# cursor:
#   - left segment (to left of cursor)
#   - cursor segment (character at cursor)
#   - right segment (to right of cursor)
def abbrev_segments
  left    = @abbrev[0, @col]
  cursor  = @abbrev[@col, 1]
  right   = @abbrev[(@col + 1)..-1] || ''
  [left, cursor, right]
end

def set_status *args
  # see ':help :echo' for why forcing a redraw here helps
  # prevent the status line from getting inadvertantly cleared
  # after our echo commands
  ::VIM::command 'redraw'
  while (highlight = args.shift) and  (text = args.shift) do
    text = VIM::escape_for_single_quotes text
    ::VIM::command "echohl #{highlight}"
    ::VIM::command "echon '#{text}'"
  end
  ::VIM::command 'echohl None'
end

end # class Prompt end # module CommandT ruby/command-t/scanner/buffer_scanner.rb [[[1 42

Copyright 2010-2011 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'command-t/vim' require 'command-t/vim/path_utilities' require 'command-t/scanner'

module CommandT

Returns a list of all open buffers.

class BufferScanner < Scanner include VIM::PathUtilities

def paths
  (0..(::VIM::Buffer.count - 1)).map do |n|
    buffer = ::VIM::Buffer[n]
    if buffer.name # beware, may be nil
      relative_path_under_working_directory buffer.name
    end
  end.compact
end

end # class BufferScanner end # module CommandT ruby/command-t/scanner/file_scanner.rb [[[1 118

Copyright 2010-2013 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'command-t/vim' require 'command-t/scanner'

module CommandT

Reads the current directory recursively for the paths to all regular files.

class FileScanner < Scanner class FileLimitExceeded < ::RuntimeError; end attr_accessor :path

def initialize path = Dir.pwd, options = {}
  @paths                = {}
  @paths_keys           = []
  @path                 = path
  @max_depth            = options[:max_depth] || 15
  @max_files            = options[:max_files] || 30_000
  @max_caches           = options[:max_caches] || 1
  @scan_dot_directories = options[:scan_dot_directories] || false
  @wild_ignore          = options[:wild_ignore]
  @base_wild_ignore     = VIM::wild_ignore
end

def paths
  return @paths[@path] if @paths.has_key?(@path)
  begin
    ensure_cache_under_limit
    @paths[@path] = []
    @depth        = 0
    @files        = 0
    @prefix_len   = @path.chomp('/').length
    set_wild_ignore(@wild_ignore)
    add_paths_for_directory @path, @paths[@path]
  rescue FileLimitExceeded
  ensure
    set_wild_ignore(@base_wild_ignore)
  end
  @paths[@path]
end

def flush
  @paths = {}
end

private

def ensure_cache_under_limit
  # Ruby 1.8 doesn't have an ordered hash, so use a separate stack to
  # track and expire the oldest entry in the cache
  if @max_caches > 0 && @paths_keys.length >= @max_caches
    @paths.delete @paths_keys.shift
  end
  @paths_keys << @path
end

def path_excluded? path
  # first strip common prefix (@path) from path to match VIM's behavior
  path = path[(@prefix_len + 1)..-1]
  path = VIM::escape_for_single_quotes path
  ::VIM::evaluate("empty(expand(fnameescape('#{path}')))").to_i == 1
end

def looped_symlink? path
  if File.symlink?(path)
    target = File.expand_path(File.readlink(path), File.dirname(path))
    target.include?(@path) || @path.include?(target)
  end
end

def set_wild_ignore(ignore)
  ::VIM::command("set wildignore=#{ignore}") if @wild_ignore
end

def add_paths_for_directory dir, accumulator
  Dir.foreach(dir) do |entry|
    next if ['.', '..'].include?(entry)
    path = File.join(dir, entry)
    unless path_excluded?(path)
      if File.file?(path)
        @files += 1
        raise FileLimitExceeded if @files > @max_files
        accumulator << path[@prefix_len + 1..-1]
      elsif File.directory?(path)
        next if @depth >= @max_depth
        next if (entry.match(/\A\./) && !@scan_dot_directories)
        next if looped_symlink?(path)
        @depth += 1
        add_paths_for_directory path, accumulator
        @depth -= 1
      end
    end
  end
rescue Errno::EACCES
  # skip over directories for which we don't have access
end

end # class FileScanner end # module CommandT ruby/command-t/scanner/jump_scanner.rb [[[1 54

Copyright 2011 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'command-t/vim' require 'command-t/vim/path_utilities' require 'command-t/scanner'

module CommandT

Returns a list of files in the jumplist.

class JumpScanner < Scanner include VIM::PathUtilities

def paths
  jumps_with_filename = jumps.lines.select do |line|
    line_contains_filename?(line)
  end
  filenames = jumps_with_filename[1..-2].map do |line|
    relative_path_under_working_directory line.split[3]
  end

  filenames.sort.uniq
end

private

def line_contains_filename? line
  line.split.count > 3
end

def jumps
  VIM::capture 'silent jumps'
end

end # class JumpScanner end # module CommandT ruby/command-t/scanner/tag_scanner.rb [[[1 49

Copyright 2011-2012 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'command-t/vim' require 'command-t/scanner'

module CommandT class TagScanner < Scanner attr_reader :include_filenames

def initialize options = {}
  @include_filenames = options[:include_filenames] || false
end

def paths
  taglist.map do |tag|
    path = tag['name']
    path << ":#{tag['filename']}" if @include_filenames
    path
  end.uniq.sort
end

private

def taglist
  ::VIM::evaluate 'taglist(".")'
end

end # class TagScanner end # module CommandT ruby/command-t/scanner.rb [[[1 28

Copyright 2010-2011 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'command-t/vim'

module CommandT class Scanner; end end # module CommandT ruby/command-t/settings.rb [[[1 77

Copyright 2010 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

module CommandT

Convenience class for saving and restoring global settings.

class Settings def initialize save end

def save
  @timeoutlen     = get_number 'timeoutlen'
  @report         = get_number 'report'
  @sidescroll     = get_number 'sidescroll'
  @sidescrolloff  = get_number 'sidescrolloff'
  @timeout        = get_bool 'timeout'
  @equalalways    = get_bool 'equalalways'
  @hlsearch       = get_bool 'hlsearch'
  @insertmode     = get_bool 'insertmode'
  @showcmd        = get_bool 'showcmd'
end

def restore
  set_number 'timeoutlen', @timeoutlen
  set_number 'report', @report
  set_number 'sidescroll', @sidescroll
  set_number 'sidescrolloff', @sidescrolloff
  set_bool 'timeout', @timeout
  set_bool 'equalalways', @equalalways
  set_bool 'hlsearch', @hlsearch
  set_bool 'insertmode', @insertmode
  set_bool 'showcmd', @showcmd
end

private

def get_number setting
  ::VIM::evaluate("&#{setting}").to_i
end

def get_bool setting
  ::VIM::evaluate("&#{setting}").to_i == 1
end

def set_number setting, value
  ::VIM::set_option "#{setting}=#{value}"
end

def set_bool setting, value
  if value
    ::VIM::set_option setting
  else
    ::VIM::set_option "no#{setting}"
  end
end

end # class Settings end # module CommandT ruby/command-t/stub.rb [[[1 42

Copyright 2010-2011 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

module CommandT class Stub @@load_error = ['command-t.vim could not load the C extension', 'Please see INSTALLATION and TROUBLE-SHOOTING in the help', 'For more information type: :help command-t']

[:flush, :show_buffer_finder, :show_file_finder, :show_tag_finder].each do |method|
  define_method(method.to_sym) { warn *@@load_error }
end

private

def warn *msg
  ::VIM::command 'echohl WarningMsg'
  msg.each { |m| ::VIM::command "echo '#{m}'" }
  ::VIM::command 'echohl none'
end

end # class Stub end # module CommandT ruby/command-t/vim/path_utilities.rb [[[1 40

Copyright 2010-2011 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'command-t/vim'

module CommandT module VIM module PathUtilities

private

  def relative_path_under_working_directory path
    # any path under the working directory will be specified as a relative
    # path to improve the readability of the buffer list etc
    pwd = File.expand_path(VIM::pwd) + '/'
    path.index(pwd) == 0 ? path[pwd.length..-1] : path
  end
end # module PathUtilities

end # module VIM end # module CommandT ruby/command-t/vim/screen.rb [[[1 32

Copyright 2010 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

module CommandT module VIM module Screen def self.lines ::VIM::evaluate('&lines').to_i end end # module Screen end # module VIM end # module CommandT ruby/command-t/vim/window.rb [[[1 38

Copyright 2010 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

module CommandT module VIM class Window def self.select window return true if $curwin == window initial = $curwin while true do ::VIM::command 'wincmd w' # cycle through windows return true if $curwin == window # have selected desired window return false if $curwin == initial # have already looped through all end end end # class Window end # module VIM end # module CommandT ruby/command-t/vim.rb [[[1 63

Copyright 2010-2013 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

require 'command-t/vim/screen' require 'command-t/vim/window'

module CommandT module VIM def self.has_syntax? ::VIM::evaluate('has("syntax")').to_i != 0 end

def self.exists? str
  ::VIM::evaluate(%{exists("#{str}")}).to_i != 0
end

def self.has_conceal?
  ::VIM::evaluate('has("conceal")').to_i != 0
end

def self.pwd
  ::VIM::evaluate 'getcwd()'
end

def self.wild_ignore
  exists?('&wildignore') && ::VIM::evaluate('&wildignore').to_s
end

# Execute cmd, capturing the output into a variable and returning it.
def self.capture cmd
  ::VIM::command 'silent redir => g:command_t_captured_output'
  ::VIM::command cmd
  ::VIM::command 'silent redir END'
  ::VIM::evaluate 'g:command_t_captured_output'
end

# Escape a string for safe inclusion in a Vim single-quoted string
# (single quotes escaped by doubling, everything else is literal)
def self.escape_for_single_quotes str
  str.gsub "'", "''"
end

end # module VIM end # module CommandT ruby/command-t/ext.c [[[1 65 // Copyright 2010 Wincent Colaiuta. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE.

#include "match.h" #include "matcher.h"

VALUE mCommandT = 0; // module CommandT VALUE cCommandTMatch = 0; // class CommandT::Match VALUE cCommandTMatcher = 0; // class CommandT::Matcher

VALUE CommandT_option_from_hash(const char *option, VALUE hash) { if (NIL_P(hash)) return Qnil; VALUE key = ID2SYM(rb_intern(option)); if (rb_funcall(hash, rb_intern("has_key?"), 1, key) == Qtrue) return rb_hash_aref(hash, key); else return Qnil; }

void Init_ext() { // module CommandT mCommandT = rb_define_module("CommandT");

// class CommandT::Match
cCommandTMatch = rb_define_class_under(mCommandT, "Match", rb_cObject);

// methods
rb_define_method(cCommandTMatch, "initialize", CommandTMatch_initialize, -1);
rb_define_method(cCommandTMatch, "matches?", CommandTMatch_matches, 0);
rb_define_method(cCommandTMatch, "to_s", CommandTMatch_to_s, 0);

// attributes
rb_define_attr(cCommandTMatch, "score", Qtrue, Qfalse); // reader: true, writer: false

// class CommandT::Matcher
cCommandTMatcher = rb_define_class_under(mCommandT, "Matcher", rb_cObject);

// methods
rb_define_method(cCommandTMatcher, "initialize", CommandTMatcher_initialize, -1);
rb_define_method(cCommandTMatcher, "sorted_matches_for", CommandTMatcher_sorted_matches_for, 2);
rb_define_method(cCommandTMatcher, "matches_for", CommandTMatcher_matches_for, 1);

} ruby/command-t/match.c [[[1 216 // Copyright 2010-2013 Wincent Colaiuta. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE.

#include "float.h" #include "match.h" #include "ext.h" #include "ruby_compat.h"

// use a struct to make passing params during recursion easier typedef struct { char *haystack_p; // pointer to the path string to be searched long haystack_len; // length of same char *needle_p; // pointer to search string (needle) long needle_len; // length of same double max_score_per_char; int dot_file; // boolean: true if str is a dot-file int always_show_dot_files; // boolean int never_show_dot_files; // boolean double *memo; // memoization } matchinfo_t;

double recursive_match(matchinfo_t *m, // sharable meta-data long haystack_idx, // where in the path string to start long needle_idx, // where in the needle string to start long last_idx, // location of last matched character double score) // cumulative score so far { double seen_score = 0; // remember best score seen via recursion int dot_file_match = 0; // true if needle matches a dot-file int dot_search = 0; // true if searching for a dot

// do we have a memoized result we can return?
double memoized = m->memo[needle_idx * m->needle_len + haystack_idx];
if (memoized != DBL_MAX)
    return memoized;

// bail early if not enough room (left) in haystack for (rest of) needle
if (m->haystack_len - haystack_idx < m->needle_len - needle_idx) {
    score = 0.0;
    goto memoize;
}

for (long i = needle_idx; i < m->needle_len; i++) {
    char c = m->needle_p[i];
    if (c == '.')
        dot_search = 1;
    int found = 0;

    // similar to above, we'll stop iterating when we know we're too close
    // to the end of the string to possibly match
    for (long j = haystack_idx;
         j <= m->haystack_len - (m->needle_len - i);
         j++, haystack_idx++) {
        char d = m->haystack_p[j];
        if (d == '.') {
            if (j == 0 || m->haystack_p[j - 1] == '/') {
                m->dot_file = 1;        // this is a dot-file
                if (dot_search)         // and we are searching for a dot
                    dot_file_match = 1; // so this must be a match
            }
        } else if (d >= 'A' && d <= 'Z') {
            d += 'a' - 'A'; // add 32 to downcase
        }

        if (c == d) {
            found = 1;
            dot_search = 0;

            // calculate score
            double score_for_char = m->max_score_per_char;
            long distance = j - last_idx;

            if (distance > 1) {
                double factor = 1.0;
                char last = m->haystack_p[j - 1];
                char curr = m->haystack_p[j]; // case matters, so get again
                if (last == '/')
                    factor = 0.9;
                else if (last == '-' ||
                        last == '_' ||
                        last == ' ' ||
                        (last >= '0' && last <= '9'))
                    factor = 0.8;
                else if (last >= 'a' && last <= 'z' &&
                        curr >= 'A' && curr <= 'Z')
                    factor = 0.8;
                else if (last == '.')
                    factor = 0.7;
                else
                    // if no "special" chars behind char, factor diminishes
                    // as distance from last matched char increases
                    factor = (1.0 / distance) * 0.75;
                score_for_char *= factor;
            }

            if (++j < m->haystack_len) {
                // bump cursor one char to the right and
                // use recursion to try and find a better match
                double sub_score = recursive_match(m, j, i, last_idx, score);
                if (sub_score > seen_score)
                    seen_score = sub_score;
            }

            score += score_for_char;
            last_idx = haystack_idx + 1;
            break;
        }
    }

    if (!found) {
        score = 0.0;
        goto memoize;
    }
}

if (m->dot_file &&
    (m->never_show_dot_files ||
     (!dot_file_match && !m->always_show_dot_files))) {
    score = 0.0;
    goto memoize;
}
score = score > seen_score ? score : seen_score;

memoize: m->memo[needle_idx * m->needle_len + haystack_idx] = score; return score; }

// Match.new needle, string, options = {} VALUE CommandTMatch_initialize(int argc, VALUE *argv, VALUE self) { // process arguments: 2 mandatory, 1 optional VALUE str, needle, options; if (rb_scan_args(argc, argv, "21", &str, &needle, &options) == 2) options = Qnil; str = StringValue(str); needle = StringValue(needle); // already downcased by caller

// check optional options hash for overrides
VALUE always_show_dot_files = CommandT_option_from_hash("always_show_dot_files", options);
VALUE never_show_dot_files = CommandT_option_from_hash("never_show_dot_files", options);

matchinfo_t m;
m.haystack_p            = RSTRING_PTR(str);
m.haystack_len          = RSTRING_LEN(str);
m.needle_p              = RSTRING_PTR(needle);
m.needle_len            = RSTRING_LEN(needle);
m.max_score_per_char    = (1.0 / m.haystack_len + 1.0 / m.needle_len) / 2;
m.dot_file              = 0;
m.always_show_dot_files = always_show_dot_files == Qtrue;
m.never_show_dot_files  = never_show_dot_files == Qtrue;

// calculate score
double score = 1.0;

// special case for zero-length search string
if (m.needle_len == 0) {

    // filter out dot files
    if (!m.always_show_dot_files) {
        for (long i = 0; i < m.haystack_len; i++) {
            char c = m.haystack_p[i];

            if (c == '.' && (i == 0 || m.haystack_p[i - 1] == '/')) {
                score = 0.0;
                break;
            }
        }
    }
} else if (m.haystack_len > 0) { // normal case

    // prepare for memoization
    double memo[m.haystack_len * m.needle_len];
    for (long i = 0, max = m.haystack_len * m.needle_len; i < max; i++)
        memo[i] = DBL_MAX;
    m.memo = memo;

    score = recursive_match(&m, 0, 0, 0, 0.0);
}

// clean-up and final book-keeping
rb_iv_set(self, "@score", rb_float_new(score));
rb_iv_set(self, "@str", str);
return Qnil;

}

VALUE CommandTMatch_matches(VALUE self) { double score = NUM2DBL(rb_iv_get(self, "@score")); return score > 0 ? Qtrue : Qfalse; }

VALUE CommandTMatch_to_s(VALUE self) { return rb_iv_get(self, "@str"); } ruby/command-t/matcher.c [[[1 169 // Copyright 2010-2013 Wincent Colaiuta. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE.

#include <stdlib.h> /* for qsort() / #include <string.h> / for strcmp() */ #include "matcher.h" #include "ext.h" #include "ruby_compat.h"

// comparison function for use with qsort int comp_alpha(const void *a, const void *b) { VALUE a_val = *(VALUE *)a; VALUE b_val = *(VALUE *)b; ID to_s = rb_intern("to_s"); VALUE a_str = rb_funcall(a_val, to_s, 0); VALUE b_str = rb_funcall(b_val, to_s, 0); char *a_p = RSTRING_PTR(a_str); long a_len = RSTRING_LEN(a_str); char *b_p = RSTRING_PTR(b_str); long b_len = RSTRING_LEN(b_str); int order = 0;

if (a_len > b_len) {
    order = strncmp(a_p, b_p, b_len);
    if (order == 0)
        order = 1; // shorter string (b) wins
} else if (a_len < b_len) {
    order = strncmp(a_p, b_p, a_len);
    if (order == 0)
        order = -1; // shorter string (a) wins
} else {
    order = strncmp(a_p, b_p, a_len);
}

return order;

}

// comparison function for use with qsort int comp_score(const void *a, const void *b) { VALUE a_val = *(VALUE *)a; VALUE b_val = *(VALUE *)b; ID score = rb_intern("score"); double a_score = RFLOAT_VALUE(rb_funcall(a_val, score, 0)); double b_score = RFLOAT_VALUE(rb_funcall(b_val, score, 0));

if (a_score > b_score)
    return -1; // a scores higher, a should appear sooner
else if (a_score < b_score)
    return 1;  // b scores higher, a should appear later
else
    return comp_alpha(a, b);

}

VALUE CommandTMatcher_initialize(int argc, VALUE *argv, VALUE self) { // process arguments: 1 mandatory, 1 optional VALUE scanner, options;

if (rb_scan_args(argc, argv, "11", &scanner, &options) == 1)
    options = Qnil;
if (NIL_P(scanner))
    rb_raise(rb_eArgError, "nil scanner");

rb_iv_set(self, "@scanner", scanner);

// check optional options hash for overrides
VALUE always_show_dot_files = CommandT_option_from_hash("always_show_dot_files", options);
if (always_show_dot_files != Qtrue)
    always_show_dot_files = Qfalse;

VALUE never_show_dot_files = CommandT_option_from_hash("never_show_dot_files", options);
if (never_show_dot_files != Qtrue)
    never_show_dot_files = Qfalse;

rb_iv_set(self, "@always_show_dot_files", always_show_dot_files);
rb_iv_set(self, "@never_show_dot_files", never_show_dot_files);

return Qnil;

}

VALUE CommandTMatcher_sorted_matches_for(VALUE self, VALUE abbrev, VALUE options) { // process optional options hash VALUE limit_option = CommandT_option_from_hash("limit", options);

// get unsorted matches
VALUE matches = CommandTMatcher_matches_for(self, abbrev);

abbrev = StringValue(abbrev);
if (RSTRING_LEN(abbrev) == 0 ||
    (RSTRING_LEN(abbrev) == 1 && RSTRING_PTR(abbrev)[0] == '.'))
    // alphabetic order if search string is only "" or "."
    qsort(RARRAY_PTR(matches), RARRAY_LEN(matches), sizeof(VALUE), comp_alpha);
else
    // for all other non-empty search strings, sort by score
    qsort(RARRAY_PTR(matches), RARRAY_LEN(matches), sizeof(VALUE), comp_score);

// apply optional limit option
long limit = NIL_P(limit_option) ? 0 : NUM2LONG(limit_option);
if (limit == 0 || RARRAY_LEN(matches) < limit)
    limit = RARRAY_LEN(matches);

// will return an array of strings, not an array of Match objects
for (long i = 0; i < limit; i++) {
    VALUE str = rb_funcall(RARRAY_PTR(matches)[i], rb_intern("to_s"), 0);
    RARRAY_PTR(matches)[i] = str;
}

// trim off any items beyond the limit
if (limit < RARRAY_LEN(matches))
    (void)rb_funcall(matches, rb_intern("slice!"), 2, LONG2NUM(limit),
        LONG2NUM(RARRAY_LEN(matches) - limit));

return matches;

}

VALUE CommandTMatcher_matches_for(VALUE self, VALUE abbrev) { if (NIL_P(abbrev)) rb_raise(rb_eArgError, "nil abbrev");

VALUE matches = rb_ary_new();
VALUE scanner = rb_iv_get(self, "@scanner");
VALUE always_show_dot_files = rb_iv_get(self, "@always_show_dot_files");
VALUE never_show_dot_files = rb_iv_get(self, "@never_show_dot_files");
VALUE options = Qnil;

if (always_show_dot_files == Qtrue) {
    options = rb_hash_new();
    rb_hash_aset(options, ID2SYM(rb_intern("always_show_dot_files")), always_show_dot_files);
} else if (never_show_dot_files == Qtrue) {
    options = rb_hash_new();
    rb_hash_aset(options, ID2SYM(rb_intern("never_show_dot_files")), never_show_dot_files);
}

abbrev = rb_funcall(abbrev, rb_intern("downcase"), 0);
VALUE paths = rb_funcall(scanner, rb_intern("paths"), 0);

for (long i = 0, max = RARRAY_LEN(paths); i < max; i++) {
    VALUE path = RARRAY_PTR(paths)[i];
    VALUE match = rb_funcall(cCommandTMatch, rb_intern("new"), 3, path, abbrev, options);
    if (rb_funcall(match, rb_intern("matches?"), 0) == Qtrue)
        rb_funcall(matches, rb_intern("push"), 1, match);
}

return matches;

} ruby/command-t/ext.h [[[1 36 // Copyright 2010 Wincent Colaiuta. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE.

#include <ruby.h>

extern VALUE mCommandT; // module CommandT extern VALUE cCommandTMatch; // class CommandT::Match extern VALUE cCommandTMatcher; // class CommandT::Matcher

// Encapsulates common pattern of checking for an option in an optional // options hash. The hash itself may be nil, but an exception will be // raised if it is not nil and not a hash. VALUE CommandT_option_from_hash(const char *option, VALUE hash);

// Debugging macro. #define ruby_inspect(obj) rb_funcall(rb_mKernel, rb_intern("p"), 1, obj) ruby/command-t/match.h [[[1 29 // Copyright 2010 Wincent Colaiuta. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE.

#include <ruby.h>

extern VALUE CommandTMatch_initialize(int argc, VALUE *argv, VALUE self); extern VALUE CommandTMatch_matches(VALUE self); extern VALUE CommandTMatch_score(VALUE self); extern VALUE CommandTMatch_to_s(VALUE self); ruby/command-t/matcher.h [[[1 30 // Copyright 2010 Wincent Colaiuta. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE.

#include <ruby.h>

extern VALUE CommandTMatcher_initialize(int argc, VALUE *argv, VALUE self); extern VALUE CommandTMatcher_sorted_matches_for(VALUE self, VALUE abbrev, VALUE options);

// most likely the function will be subsumed by the sorted_matcher_for function extern VALUE CommandTMatcher_matches_for(VALUE self, VALUE abbrev); ruby/command-t/ruby_compat.h [[[1 49 // Copyright 2010 Wincent Colaiuta. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // 2. Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE.

#include <ruby.h>

// for compatibility with older versions of Ruby which don't declare RSTRING_PTR #ifndef RSTRING_PTR #define RSTRING_PTR(s) (RSTRING(s)->ptr) #endif

// for compatibility with older versions of Ruby which don't declare RSTRING_LEN #ifndef RSTRING_LEN #define RSTRING_LEN(s) (RSTRING(s)->len) #endif

// for compatibility with older versions of Ruby which don't declare RARRAY_PTR #ifndef RARRAY_PTR #define RARRAY_PTR(a) (RARRAY(a)->ptr) #endif

// for compatibility with older versions of Ruby which don't declare RARRAY_LEN #ifndef RARRAY_LEN #define RARRAY_LEN(a) (RARRAY(a)->len) #endif

// for compatibility with older versions of Ruby which don't declare RFLOAT_VALUE #ifndef RFLOAT_VALUE #define RFLOAT_VALUE(f) (RFLOAT(f)->value) #endif ruby/command-t/depend [[[1 24

Copyright 2010 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without

modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice,

this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,

this list of conditions and the following disclaimer in the documentation

and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE

ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE

LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR

CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF

SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS

INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN

CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)

ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE

POSSIBILITY OF SUCH DAMAGE.

CFLAGS += -std=c99 -Wall -Wextra -Wno-unused-parameter doc/command-t.txt [[[1 941 command-t.txt Command-T plug-in for Vim command-t

CONTENTS command-t-contents

  1. Introduction |command-t-intro|
  2. Requirements |command-t-requirements|
  3. Installation |command-t-installation|
  4. Managing using Pathogen |command-t-pathogen|
  5. Trouble-shooting |command-t-trouble-shooting|
  6. Usage |command-t-usage|
  7. Commands |command-t-commands|
  8. Mappings |command-t-mappings|
  9. Options |command-t-options|
  10. Authors |command-t-authors|
  11. Development |command-t-development|
  12. Website |command-t-website|
  13. Donations |command-t-donations|
  14. License |command-t-license|
  15. History |command-t-history|

INTRODUCTION command-t-intro

The Command-T plug-in provides an extremely fast, intuitive mechanism for opening files and buffers with a minimal number of keystrokes. It's named "Command-T" because it is inspired by the "Go to File" window bound to Command-T in TextMate.

Files are selected by typing characters that appear in their paths, and are ordered by an algorithm which knows that characters that appear in certain locations (for example, immediately after a path separator) should be given more weight.

To search efficiently, especially in large projects, you should adopt a "path-centric" rather than a "filename-centric" mentality. That is you should think more about where the desired file is found rather than what it is called. This means narrowing your search down by including some characters from the upper path components rather than just entering characters from the filename itself.

Screencasts demonstrating the plug-in can be viewed at:

https://wincent.com/products/command-t

REQUIREMENTS command-t-requirements

The plug-in requires Vim compiled with Ruby support, a compatible Ruby installation at the operating system level, and a C compiler to build the Ruby extension.

  1. Vim compiled with Ruby support

You can check for Ruby support by launching Vim with the --version switch:

vim --version

If "+ruby" appears in the version information then your version of Vim has Ruby support.

Another way to check is to simply try using the :ruby command from within Vim itself:

:ruby 1

If your Vim lacks support you'll see an error message like this:

E319: Sorry, the command is not available in this version

The version of Vim distributed with Mac OS X does not include Ruby support, while MacVim does; it is available from:

http://github.com/b4winckler/macvim/downloads

For Windows users, the Vim 7.2 executable available from www.vim.org does include Ruby support, and is recommended over version 7.3 (which links against Ruby 1.9, but apparently has some bugs that need to be resolved).

  1. Ruby

In addition to having Ruby support in Vim, your system itself must have a compatible Ruby install. "Compatible" means the same version as Vim itself links against. If you use a different version then Command-T is unlikely to work (see TROUBLE-SHOOTING below).

On Mac OS X Snow Leopard, the system comes with Ruby 1.8.7 and all recent versions of MacVim (the 7.2 snapshots and 7.3) are linked against it.

On Linux and similar platforms, the linked version of Ruby will depend on your distribution. You can usually find this out by examining the compilation and linking flags displayed by the |:version| command in Vim, and by looking at the output of:

:ruby puts RUBY_VERSION

A suitable Ruby environment for Windows can be installed using the Ruby 1.8.7-p299 RubyInstaller available at:

http://rubyinstaller.org/downloads/archives

If using RubyInstaller be sure to download the installer executable, not the 7-zip archive. When installing mark the checkbox "Add Ruby executables to your PATH" so that Vim can find them.

  1. C compiler

Part of Command-T is implemented in C as a Ruby extension for speed, allowing it to work responsively even on directory hierarchies containing enormous numbers of files. As such, a C compiler is required in order to build the extension and complete the installation.

On Mac OS X, this can be obtained by installing the Xcode Tools that come on the Mac OS X install disc.

On Windows, the RubyInstaller Development Kit can be used to conveniently install the necessary tool chain:

http://rubyinstaller.org/downloads/archives

At the time of writing, the appropriate development kit for use with Ruby 1.8.7 is DevKit-3.4.5r3-20091110.

To use the Development Kit extract the archive contents to your C:\Ruby folder.

INSTALLATION command-t-installation

Command-T is distributed as a "vimball" which means that it can be installed by opening it in Vim and then sourcing it:

:e command-t.vba :so %

The files will be installed in your |'runtimepath'|. To check where this is you can issue:

:echo &rtp

The C extension must then be built, which can be done from the shell. If you use a typical |'runtimepath'| then the files were installed inside ~/.vim and you can build the extension with:

cd ~/.vim/ruby/command-t ruby extconf.rb make

Note: If you are an RVM or rbenv user, you must perform the build using the same version of Ruby that Vim itself is linked against. This will often be the system Ruby, which can be selected before issuing the "make" command with one of the following commands:

rvm use system rbenv local system

Note: Make sure you compile targeting the same architecture Vim was built for. For instance, MacVim binaries are built for i386, but sometimes GCC compiles for x86_64. First you have to check the platform Vim was built for:

vim --version ... Compilation: gcc ... -arch i386 ... ...

and make sure you use the correct ARCHFLAGS during compilation:

export ARCHFLAGS="-arch i386" make

MANAGING USING PATHOGEN command-t-pathogen

Pathogen is a plugin that allows you to maintain plugin installations in separate, isolated subdirectories under the "bundle" directory in your |'runtimepath'|. The following examples assume that you already have Pathogen installed and configured, and that you are installing into ~/.vim/bundle. For more information about Pathogen, see:

http://www.vim.org/scripts/script.php?script_id=2332

If you manage your entire ~/.vim folder using Git then you can add the Command-T repository as a submodule:

cd ~/.vim git submodule add git://git.wincent.com/command-t.git bundle/command-t git submodule init

Or if you just wish to do a simple clone instead of using submodules:

cd ~/.vim git clone git://git.wincent.com/command-t.git bundle/command-t

Once you have a local copy of the repository you can update it at any time with:

cd ~/.vim/bundle/command-t git pull

Or you can switch to a specific release with:

cd ~/.vim/bundle/command-t git checkout 0.8b

After installing or updating you must build the extension:

cd ~/.vim/bundle/command-t/ruby/command-t ruby extconf.rb make

While the Vimball installation automatically generates the help tags, under Pathogen it is necessary to do so explicitly from inside Vim:

:call pathogen#helptags()

TROUBLE-SHOOTING command-t-trouble-shooting

Most installation problems are caused by a mismatch between the version of Ruby on the host operating system, and the version of Ruby that Vim itself linked against at compile time. For example, if one is 32-bit and the other is 64-bit, or one is from the Ruby 1.9 series and the other is from the 1.8 series, then the plug-in is not likely to work.

As such, on Mac OS X, I recommend using the standard Ruby that comes with the system (currently 1.8.7) along with the latest version of MacVim (currently version 7.3). If you wish to use custom builds of Ruby or of MacVim (not recommmended) then you will have to take extra care to ensure that the exact same Ruby environment is in effect when building Ruby, Vim and the Command-T extension.

For Windows, the following combination is known to work:

If a problem occurs the first thing you should do is inspect the output of:

ruby extconf.rb make

During the installation, and:

vim --version

And compare the compilation and linker flags that were passed to the extension and to Vim itself when they were built. If the Ruby-related flags or architecture flags are different then it is likely that something has changed in your Ruby environment and the extension may not work until you eliminate the discrepancy.

USAGE command-t-usage

Bring up the Command-T file window by typing:

t

This mapping is set up automatically for you, provided you do not already have a mapping for t or |:CommandT|. You can also bring up the file window by issuing the command:

:CommandT

A prompt will appear at the bottom of the screen along with a file window showing all of the files in the current directory (as returned by the |:pwd| command).

For the most efficient file navigation within a project it's recommended that you |:cd| into the root directory of your project when starting to work on it. If you wish to open a file from outside of the project folder you can pass in an optional path argument (relative or absolute) to |:CommandT|:

:CommandT ../path/to/other/files

Type letters in the prompt to narrow down the selection, showing only the files whose paths contain those letters in the specified order. Letters do not need to appear consecutively in a path in order for it to be classified as a match.

Once the desired file has been selected it can be opened by pressing . (By default files are opened in the current window, but there are other mappings that you can use to open in a vertical or horizontal split, or in a new tab.) Note that if you have |'nohidden'| set and there are unsaved changes in the current window when you press then opening in the current window would fail; in this case Command-T will open the file in a new split.

The following mappings are active when the prompt has focus:

<BS>        delete the character to the left of the cursor
<Del>       delete the character at the cursor
<Left>      move the cursor one character to the left
<C-h>       move the cursor one character to the left
<Right>     move the cursor one character to the right
<C-l>       move the cursor one character to the right
<C-a>       move the cursor to the start (left)
<C-e>       move the cursor to the end (right)
<C-u>       clear the contents of the prompt
<Tab>       change focus to the file listing

The following mappings are active when the file listing has focus:

<Tab>       change focus to the prompt

The following mappings are active when either the prompt or the file listing has focus:

<CR>        open the selected file
<C-CR>      open the selected file in a new split window
<C-s>       open the selected file in a new split window
<C-v>       open the selected file in a new vertical split window
<C-t>       open the selected file in a new tab
<C-j>       select next file in the file listing
<C-n>       select next file in the file listing
<Down>      select next file in the file listing
<C-k>       select previous file in the file listing
<C-p>       select previous file in the file listing
<Up>        select previous file in the file listing
<C-f>       flush the cache (see |:CommandTFlush| for details)
<C-q>       place the current matches in the quickfix window
<C-c>       cancel (dismisses file listing)

The following is also available on terminals which support it:

<Esc>       cancel (dismisses file listing)

Note that the default mappings can be overriden by setting options in your ~/.vimrc file (see the OPTIONS section for a full list of available options).

In addition, when the file listing has focus, typing a character will cause the selection to jump to the first path which begins with that character. Typing multiple characters consecutively can be used to distinguish between paths which begin with the same prefix.

COMMANDS command-t-commands

                                            *:CommandT*

|:CommandT| Brings up the Command-T file window, starting in the current working directory as returned by the|:pwd| command.

                                            *:CommandTBuffer*

|:CommandTBuffer|Brings up the Command-T buffer window. This works exactly like the standard file window, except that the selection is limited to files that you already have open in buffers.

                                            *:CommandTJumps*

|:CommandTJump| Brings up the Command-T jumplist window. This works exactly like the standard file window, except that the selection is limited to files that you already have in the jumplist. Note that jumps can persist across Vim sessions (see Vim's |jumplist| documentation for more info).

                                            *:CommandTTag*

|:CommandTTag| Brings up the Command-T window tags window, which can be used to select from the tags, if any, returned by Vim's |taglist()| function. See Vim's |tag| documentation for general info on tags.

                                            *:CommandTFlush*

|:CommandTFlush|Instructs the plug-in to flush its path cache, causing the directory to be rescanned for new or deleted paths the next time the file window is shown (pressing when a match listing is visible flushes the cache immediately; this mapping is configurable via the |g:CommandTRefreshMap| setting). In addition, all configuration settings are re-evaluated, causing any changes made to settings via the |:let| command to be picked up.

MAPPINGS command-t-mappings

By default Command-T comes with only two mappings:

t bring up the Command-T file window b bring up the Command-T buffer window

However, Command-T won't overwrite a pre-existing mapping so if you prefer to define different mappings use lines like these in your ~/.vimrc:

nnoremap t :CommandT nnoremap b :CommandTBuffer

Replacing "t" or "b" with your mapping of choice.

Note that in the case of MacVim you actually can map to Command-T (written as in Vim) in your ~/.gvimrc file if you first unmap the existing menu binding of Command-T to "New Tab":

if has("gui_macvim") macmenu &File.New\ Tab key= map :CommandT endif

When the Command-T window is active a number of other additional mappings become available for doing things like moving between and selecting matches. These are fully described above in the USAGE section, and settings for overriding the mappings are listed below under OPTIONS.

OPTIONS command-t-options

A number of options may be set in your ~/.vimrc to influence the behaviour of the plug-in. To set an option, you include a line like this in your ~/.vimrc:

let g:CommandTMaxFiles=20000

To have Command-T pick up new settings immediately (that is, without having to restart Vim) you can issue the |:CommandTFlush| command after making changes via |:let|.

Following is a list of all available options:

                                           *g:CommandTMaxFiles*

|g:CommandTMaxFiles| number (default 30000)

  The maximum number of files that will be considered when scanning the
  current directory. Upon reaching this number scanning stops. This
  limit applies only to file listings and is ignored for buffer
  listings.

                                           *g:CommandTMaxDepth*

|g:CommandTMaxDepth| number (default 15)

  The maximum depth (levels of recursion) to be explored when scanning the
  current directory. Any directories at levels beyond this depth will be
  skipped.

                                           *g:CommandTMaxCachedDirectories*

|g:CommandTMaxCachedDirectories| number (default 1)

  The maximum number of directories whose contents should be cached when
  recursively scanning. With the default value of 1, each time you change
  directories the cache will be emptied and Command-T will have to
  rescan. Higher values will make Command-T hold more directories in the
  cache, bringing performance at the cost of memory usage. If set to 0,
  there is no limit on the number of cached directories.

                                           *g:CommandTMaxHeight*

|g:CommandTMaxHeight| number (default: 0)

  The maximum height in lines the match window is allowed to expand to.
  If set to 0, the window will occupy as much of the available space as
  needed to show matching entries.

                                           *g:CommandTMinHeight*

|g:CommandTMinHeight| number (default: 0)

  The minimum height in lines the match window is allowed to shrink to.
  If set to 0, will default to a single line. If set above the max height,
  will default to |g:CommandTMaxHeight|.

                                           *g:CommandTAlwaysShowDotFiles*

|g:CommandTAlwaysShowDotFiles| boolean (default: 0)

  When showing the file listing Command-T will by default show dot-files
  only if the entered search string contains a dot that could cause a
  dot-file to match. When set to a non-zero value, this setting instructs
  Command-T to always include matching dot-files in the match list
  regardless of whether the search string contains a dot. See also
  |g:CommandTNeverShowDotFiles|. Note that this setting only influences
  the file listing; the buffer listing treats dot-files like any other
  file.

                                           *g:CommandTNeverShowDotFiles*

|g:CommandTNeverShowDotFiles| boolean (default: 0)

  In the file listing, Command-T will by default show dot-files if the
  entered search string contains a dot that could cause a dot-file to
  match. When set to a non-zero value, this setting instructs Command-T to
  never show dot-files under any circumstances. Note that it is
  contradictory to set both this setting and
  |g:CommandTAlwaysShowDotFiles| to true, and if you do so Vim will suffer
  from headaches, nervous twitches, and sudden mood swings. This setting
  has no effect in buffer listings, where dot files are treated like any
  other file.

                                           *g:CommandTScanDotDirectories*

|g:CommandTScanDotDirectories| boolean (default: 0)

  Normally Command-T will not recurse into "dot-directories" (directories
  whose names begin with a dot) while performing its initial scan. Set
  this setting to a non-zero value to override this behavior and recurse.
  Note that this setting is completely independent of the
  |g:CommandTAlwaysShowDotFiles| and |g:CommandTNeverShowDotFiles|
  settings; those apply only to the selection and display of matches
  (after scanning has been performed), whereas
  |g:CommandTScanDotDirectories| affects the behaviour at scan-time.

  Note also that even with this setting off you can still use Command-T to
  open files inside a "dot-directory" such as ~/.vim, but you have to use
  the |:cd| command to change into that directory first. For example:

    :cd ~/.vim
    :CommandT

                                           *g:CommandTMatchWindowAtTop*

|g:CommandTMatchWindowAtTop| boolean (default: 0)

  When this setting is off (the default) the match window will appear at
  the bottom so as to keep it near to the prompt. Turning it on causes the
  match window to appear at the top instead. This may be preferable if you
  want the best match (usually the first one) to appear in a fixed location
  on the screen rather than moving as the number of matches changes during
  typing.

                                            *g:CommandTMatchWindowReverse*

|g:CommandTMatchWindowReverse| boolean (default: 0)

  When this setting is off (the default) the matches will appear from
  top to bottom with the topmost being selected. Turning it on causes the
  matches to be reversed so the best match is at the bottom and the
  initially selected match is the bottom most. This may be preferable if
  you want the best match to appear in a fixed location on the screen
  but still be near the prompt at the bottom.

                                            *g:CommandTTagIncludeFilenames*

|g:CommandTTagIncludeFilenames| boolean (default: 0)

  When this setting is off (the default) the matches in the |:CommandTTag|
  listing do not include filenames.

                                            *g:CommandTHighlightColor*

|g:CommandTHighlightColor| string (default: 'PmenuSel')

  Specifies the highlight color that will be used to show the currently
  selected item in the match listing window.

                                            *g:CommandTWildIgnore*

|g:CommandTWildIgnore| string (default: none)

  Optionally override Vim's global |'wildignore'| setting during Command-T
  seaches. If you wish to supplement rather than replace the global
  setting, you can use a syntax like:

    let g:CommandTWildIgnore=&wildignore . ",**/bower_components/*"

  See also |command-t-wildignore|.

As well as the basic options listed above, there are a number of settings that can be used to override the default key mappings used by Command-T. For example, to set as the mapping for cancelling (dismissing) the Command-T window, you would add the following to your ~/.vimrc:

let g:CommandTCancelMap=''

Multiple, alternative mappings may be specified using list syntax:

let g:CommandTCancelMap=['', '']

Following is a list of all map settings and their defaults:

                          Setting   Default mapping(s)

                                  *g:CommandTBackspaceMap*
          |g:CommandTBackspaceMap|  <BS>

                                  *g:CommandTDeleteMap*
             |g:CommandTDeleteMap|  <Del>

                                  *g:CommandTAcceptSelectionMap*
    |g:CommandTAcceptSelectionMap|  <CR>

                                  *g:CommandTAcceptSelectionSplitMap*

|g:CommandTAcceptSelectionSplitMap|

                                  *g:CommandTAcceptSelectionTabMap*
 |g:CommandTAcceptSelectionTabMap|  <C-t>

                                  *g:CommandTAcceptSelectionVSplitMap*

|g:CommandTAcceptSelectionVSplitMap|

                                  *g:CommandTToggleFocusMap*
        |g:CommandTToggleFocusMap|  <Tab>

                                  *g:CommandTCancelMap*
             |g:CommandTCancelMap|  <C-c>
                                  <Esc> (not on all terminals)

                                  *g:CommandTSelectNextMap*
         |g:CommandTSelectNextMap|  <C-n>
                                  <C-j>
                                  <Down>

                                  *g:CommandTSelectPrevMap*
         |g:CommandTSelectPrevMap|  <C-p>
                                  <C-k>
                                  <Up>

                                  *g:CommandTClearMap*
              |g:CommandTClearMap|  <C-u>

                                  *g:CommandTRefreshMap*
            |g:CommandTRefreshMap|  <C-f>

                                  *g:CommandTQuickfixMap*
           |g:CommandTQuickfixMap|  <C-q>

                                  *g:CommandTCursorLeftMap*
         |g:CommandTCursorLeftMap|  <Left>
                                  <C-h>

                                  *g:CommandTCursorRightMap*
        |g:CommandTCursorRightMap|  <Right>
                                  <C-l>

                                  *g:CommandTCursorEndMap*
          |g:CommandTCursorEndMap|  <C-e>

                                  *g:CommandTCursorStartMap*
        |g:CommandTCursorStartMap|  <C-a>

In addition to the options provided by Command-T itself, some of Vim's own settings can be used to control behavior:

                                           *command-t-wildignore*

|'wildignore'| string (default: '')

  Vim's |'wildignore'| setting is used to determine which files should be
  excluded from listings. This is a comma-separated list of glob patterns.
  It defaults to the empty string, but common settings include "*.o,*.obj"
  (to exclude object files) or ".git,.svn" (to exclude SCM metadata
  directories). For example:

    :set wildignore+=*.o,*.obj,.git

  A pattern such as "vendor/rails/**" would exclude all files and
  subdirectories inside the "vendor/rails" directory (relative to
  directory Command-T starts in).

  See the |'wildignore'| documentation for more information.

  If you want to influence Command-T's file exclusion behavior without
  changing your global |'wildignore'| setting, you can use the
  |g:CommandTWildIgnore| setting to apply an override that takes effect
  only during Command-T searches.

AUTHORS command-t-authors

Command-T is written and maintained by Wincent Colaiuta win@wincent.com. Other contributors that have submitted patches include (in alphabetical order):

Anthony Panozzo Mike Lundy Sung Pae Daniel Hahler Nate Kane Thomas Pelletier Felix Tjandrawibawa Nicholas Alpi Victor Hugo Borja Gary Bernhardt Nadav Samet Vít Ondruch Ivan Ukhov Noon Silk Woody Peterson Jeff Kreeftmeijer Paul Jolly Yan Pritzker Lucas de Vries Rainux Luo Zak Johnson Marcus Brito Scott Bronson Marian Schubert Seth Fowler Matthew Todd Steven Moazami

As this was the first Vim plug-in I had ever written I was heavily influenced by the design of the LustyExplorer plug-in by Stephen Bach, which I understand is one of the largest Ruby-based Vim plug-ins to date.

While the Command-T codebase doesn't contain any code directly copied from LustyExplorer, I did use it as a reference for answers to basic questions (like "How do you do 'X' in a Ruby-based Vim plug-in?"), and also copied some basic architectural decisions (like the division of the code into Prompt, Settings and MatchWindow classes).

LustyExplorer is available from:

http://www.vim.org/scripts/script.php?script_id=1890

DEVELOPMENT command-t-development

Development in progress can be inspected via the project's Git web-based repository browser at:

https://wincent.com/repos/command-t

the clone URL for which is:

git://git.wincent.com/command-t.git

Mirrors exist on GitHub and Gitorious; these are automatically updated once per hour from the authoritative repository:

https://github.com/wincent/command-t https://gitorious.org/command-t/command-t

Patches are welcome via the usual mechanisms (pull requests, email, posting to the project issue tracker etc).

As many users choose to track Command-T using Pathogen, which often means running a version later than the last official release, the intention is that the "master" branch should be kept in a stable and reliable state as much as possible.

Riskier changes are first cooked on the "next" branch for a period before being merged into master. You can track this branch if you're feeling wild and experimental, but note that the "next" branch may periodically be rewound (force-updated) to keep it in sync with the "master" branch after each official release.

WEBSITE command-t-website

The official website for Command-T is:

https://wincent.com/products/command-t

The latest release will always be available from there.

A copy of each release is also available from the official Vim scripts site at:

http://www.vim.org/scripts/script.php?script_id=3025

Bug reports should be submitted to the issue tracker at:

https://wincent.com/issues

DONATIONS command-t-donations

Command-T itself is free software released under the terms of the BSD license. If you would like to support further development you can make a donation via PayPal to win@wincent.com:

https://wincent.com/products/command-t/donations

LICENSE command-t-license

Copyright 2010-2013 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

HISTORY command-t-history

1.5.1 (23 September 2013)

  • exclude large benchmark fixture file from source exports (patch from Vít Ondruch)

1.5 (18 September 2013)

  • don't scan "pathological" filesystem structures (ie. circular or self-referential symlinks; patch from Marcus Brito)
  • gracefully handle files starting with "+" (patch from Ivan Ukhov)
  • switch default selection highlight color for better readability (suggestion from André Arko), but make it possible to configure via the |g:CommandTHighlightColor| setting
  • added a mapping to take the current matches and put then in the quickfix window
  • performance improvements, particularly noticeable with large file hierarchies
  • added |g:CommandTWildIgnore| setting (patch from Paul Jolly)

1.4 (20 June 2012)

  • added |:CommandTTag| command (patches from Noon Silk)
  • turn off |'colorcolumn'| and |'relativenumber'| in the match window (patch from Jeff Kreeftmeijer)
  • documentation update (patch from Nicholas Alpi)
  • added |:CommandTMinHeight| option (patch from Nate Kane)
  • highlight (by underlining) matched characters in the match listing (requires Vim to have been compiled with the +conceal feature, which is available in Vim 7.3 or later; patch from Steven Moazami)
  • added the ability to flush the cache while the match window is open using

1.3.1 (18 December 2011)

  • fix jumplist navigation under Ruby 1.9.x (patch from Woody Peterson)

1.3 (27 November 2011)

  • added the option to maintain multiple caches when changing among directories; see the accompanying |g:CommandTMaxCachedDirectories| setting
  • added the ability to navigate using the Vim jumplist (patch from Marian Schubert)

1.2.1 (30 April 2011)

  • Remove duplicate copy of the documentation that was causing "Duplicate tag" errors
  • Mitigate issue with distracting blinking cursor in non-GUI versions of Vim (patch from Steven Moazami)

1.2 (30 April 2011)

  • added |g:CommandTMatchWindowReverse| option, to reverse the order of items in the match listing (patch from Steven Moazami)

1.1b2 (26 March 2011)

  • fix a glitch in the release process; the plugin itself is unchanged since 1.1b

1.1b (26 March 2011)

  • add |:CommandTBuffer| command for quickly selecting among open buffers

1.0.1 (5 January 2011)

  • work around bug when mapping |:CommandTFlush|, wherein the default mapping for |:CommandT| would not be set up
  • clean up when leaving the Command-T buffer via unexpected means (such as with or similar)

1.0 (26 November 2010)

  • make relative path simplification work on Windows

1.0b (5 November 2010)

  • work around platform-specific Vim 7.3 bug seen by some users (wherein Vim always falsely reports to Ruby that the buffer numbers is 0)
  • re-use the buffer that is used to show the match listing, rather than throwing it away and recreating it each time Command-T is shown; this stops the buffer numbers from creeping up needlessly

0.9 (8 October 2010)

  • use relative paths when opening files inside the current working directory in order to keep buffer listings as brief as possible (patch from Matthew Todd)

0.8.1 (14 September 2010)

  • fix mapping issues for users who have set |'notimeout'| (patch from Sung Pae)

0.8 (19 August 2010)

  • overrides for the default mappings can now be lists of strings, allowing multiple mappings to be defined for any given action
  • t mapping only set up if no other map for |:CommandT| exists (patch from Scott Bronson)
  • prevent folds from appearing in the match listing
  • tweaks to avoid the likelihood of "Not enough room" errors when trying to open files
  • watch out for "nil" windows when restoring window dimensions
  • optimizations (avoid some repeated downcasing)
  • move all Ruby files under the "command-t" subdirectory and avoid polluting the "Vim" module namespace

0.8b (11 July 2010)

  • large overhaul of the scoring algorithm to make the ordering of returned results more intuitive; given the scope of the changes and room for optimization of the new algorithm, this release is labelled as "beta"

0.7 (10 June 2010)

  • handle more |'wildignore'| patterns by delegating to Vim's own |expand()| function; with this change it is now viable to exclude patterns such as 'vendor/rails/**' in addition to filename-only patterns like '*.o' and '.git' (patch from Mike Lundy)
  • always sort results alphabetically for empty search strings; this eliminates filesystem-specific variations (patch from Mike Lundy)

0.6 (28 April 2010)

  • |:CommandT| now accepts an optional parameter to specify the starting directory, temporarily overriding the usual default of Vim's |:pwd|
  • fix truncated paths when operating from root directory

0.5.1 (11 April 2010)

  • fix for Ruby 1.9 compatibility regression introduced in 0.5
  • documentation enhancements, specifically targetted at Windows users

0.5 (3 April 2010)

  • |:CommandTFlush| now re-evaluates settings, allowing changes made via |let| to be picked up without having to restart Vim
  • fix premature abort when scanning very deep directory hierarchies
  • remove broken || key mapping on vt100 and xterm terminals
  • provide settings for overriding default mappings
  • minor performance optimization

0.4 (27 March 2010)

  • add |g:CommandTMatchWindowAtTop| setting (patch from Zak Johnson)
  • documentation fixes and enhancements
  • internal refactoring and simplification

0.3 (24 March 2010)

  • add |g:CommandTMaxHeight| setting for controlling the maximum height of the match window (patch from Lucas de Vries)
  • fix bug where |'list'| setting might be inappropriately set after dismissing Command-T
  • compatibility fix for different behaviour of "autoload" under Ruby 1.9.1
  • avoid "highlight group not found" warning when run under a version of Vim that does not have syntax highlighting support
  • open in split when opening normally would fail due to |'hidden'| and |'modified'| values

0.2 (23 March 2010)

  • compatibility fixes for compilation under Ruby 1.9 series
  • compatibility fixes for compilation under Ruby 1.8.5
  • compatibility fixes for Windows and other non-UNIX platforms
  • suppress "mapping already exists" message if t mapping is already defined when plug-in is loaded
  • exclude paths based on |'wildignore'| setting rather than a hardcoded regular expression

0.1 (22 March 2010)

  • initial public release

vim:tw=78:ft=help: plugin/command-t.vim [[[1 190 " command-t.vim " Copyright 2010-2013 Wincent Colaiuta. All rights reserved. " " Redistribution and use in source and binary forms, with or without " modification, are permitted provided that the following conditions are met: " " 1. Redistributions of source code must retain the above copyright notice, " this list of conditions and the following disclaimer. " 2. Redistributions in binary form must reproduce the above copyright notice, " this list of conditions and the following disclaimer in the documentation " and/or other materials provided with the distribution. " " THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" " AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE " IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE " ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE " LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR " CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF " SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS " INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN " CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) " ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE " POSSIBILITY OF SUCH DAMAGE.

if exists("g:command_t_loaded") || &cp finish endif let g:command_t_loaded = 1

command CommandTBuffer call CommandTShowBufferFinder() command CommandTJump call CommandTShowJumpFinder() command CommandTTag call CommandTShowTagFinder() command -nargs=? -complete=dir CommandT call CommandTShowFileFinder() command CommandTFlush call CommandTFlush()

if !hasmapto(':CommandT') silent! nnoremap t :CommandT endif

if !hasmapto(':CommandTBuffer') silent! nnoremap b :CommandTBuffer endif

function s:CommandTRubyWarning() echohl WarningMsg echo "command-t.vim requires Vim to be compiled with Ruby support" echo "For more information type: :help command-t" echohl none endfunction

function s:CommandTShowBufferFinder() if has('ruby') ruby $command_t.show_buffer_finder else call s:CommandTRubyWarning() endif endfunction

function s:CommandTShowFileFinder(arg) if has('ruby') ruby $command_t.show_file_finder else call s:CommandTRubyWarning() endif endfunction

function s:CommandTShowJumpFinder() if has('ruby') ruby $command_t.show_jump_finder else call s:CommandTRubyWarning() endif endfunction

function s:CommandTShowTagFinder() if has('ruby') ruby $command_t.show_tag_finder else call s:CommandTRubyWarning() endif endfunction

function s:CommandTFlush() if has('ruby') ruby $command_t.flush else call s:CommandTRubyWarning() endif endfunction

if !has('ruby') finish endif

function CommandTHandleKey(arg) ruby $command_t.handle_key endfunction

function CommandTBackspace() ruby $command_t.backspace endfunction

function CommandTDelete() ruby $command_t.delete endfunction

function CommandTAcceptSelection() ruby $command_t.accept_selection endfunction

function CommandTAcceptSelectionTab() ruby $command_t.accept_selection :command => 'tabe' endfunction

function CommandTAcceptSelectionSplit() ruby $command_t.accept_selection :command => 'sp' endfunction

function CommandTAcceptSelectionVSplit() ruby $command_t.accept_selection :command => 'vs' endfunction

function CommandTQuickfix() ruby $command_t.quickfix endfunction

function CommandTRefresh() ruby $command_t.refresh endfunction

function CommandTToggleFocus() ruby $command_t.toggle_focus endfunction

function CommandTCancel() ruby $command_t.cancel endfunction

function CommandTSelectNext() ruby $command_t.select_next endfunction

function CommandTSelectPrev() ruby $command_t.select_prev endfunction

function CommandTClear() ruby $command_t.clear endfunction

function CommandTCursorLeft() ruby $command_t.cursor_left endfunction

function CommandTCursorRight() ruby $command_t.cursor_right endfunction

function CommandTCursorEnd() ruby $command_t.cursor_end endfunction

function CommandTCursorStart() ruby $command_t.cursor_start endfunction

ruby << EOF

require Ruby files

begin # prepare controller require 'command-t/vim' require 'command-t/controller' $command_t = CommandT::Controller.new rescue LoadError load_path_modified = false ::VIM::evaluate('&runtimepath').to_s.split(',').each do |path| lib = "#{path}/ruby" if !$LOAD_PATH.include?(lib) and File.exist?(lib) $LOAD_PATH << lib load_path_modified = true end end retry if load_path_modified

# could get here if C extension was not compiled, or was compiled
# for the wrong architecture or Ruby version
require 'command-t/stub'
$command_t = CommandT::Stub.new

end EOF

About

Passcode view controller for iPhone/iPod.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Objective-C 100.0%