1 # Copyright 2010-2011 Wincent Colaiuta. All rights reserved.
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions are met:
6 # 1. Redistributions of source code must retain the above copyright notice,
7 # this list of conditions and the following disclaimer.
8 # 2. Redistributions in binary form must reproduce the above copyright notice,
9 # this list of conditions and the following disclaimer in the documentation
10 # and/or other materials provided with the distribution.
12 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
13 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14 # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15 # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
16 # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
22 # POSSIBILITY OF SUCH DAMAGE.
24 require 'command-t/finder/buffer_finder'
25 require 'command-t/finder/file_finder'
26 require 'command-t/match_window'
27 require 'command-t/prompt'
28 require 'command-t/vim/path_utilities'
32 include VIM
::PathUtilities
36 @buffer_finder = CommandT
::BufferFinder.new
41 def show_buffer_finder
43 @active_finder = @buffer_finder
48 # optional parameter will be desired starting directory, or ""
49 @path = File
.expand_path(::VIM::evaluate('a:arg'), VIM
::pwd)
50 @file_finder.path
= @path
51 @active_finder = @file_finder
54 # probably a problem with the optional parameter
55 @match_window.print_no_such_file_or_directory
60 if VIM
::Window.select
@initial_window
61 if @initial_buffer.number
== 0
62 # upstream bug: buffer number misreported as 0
63 # see: https://wincent.com/issues/1617
64 ::VIM::command "silent b #{@initial_buffer.name}"
66 ::VIM::command "silent b #{@initial_buffer.number}"
77 key
= ::VIM::evaluate('a:arg').to_i
.chr
82 @match_window.find key
100 def accept_selection options
= {}
101 selection
= @match_window.selection
103 open_selection(selection
, options
) unless selection
.nil?
107 @focus.unfocus
# old focus
108 @focus = @focus == @prompt ? @match_window : @prompt
109 @focus.focus
# new focus
117 @match_window.select_next
121 @match_window.select_prev
130 @prompt.cursor_left
if @focus == @prompt
134 @prompt.cursor_right
if @focus == @prompt
138 @prompt.cursor_end
if @focus == @prompt
142 @prompt.cursor_start
if @focus == @prompt
156 @initial_window = $curwin
157 @initial_buffer = $curbuf
158 @match_window = MatchWindow
.new \
160 :match_window_at_top => get_bool('g:CommandTMatchWindowAtTop'),
161 :match_window_reverse => get_bool('g:CommandTMatchWindowReverse')
164 register_for_key_presses
165 clear
# clears prompt and lists matches
168 def set_up_max_height
169 @max_height = get_number('g:CommandTMaxHeight') || 0
172 def set_up_file_finder
173 @file_finder = CommandT
::FileFinder.new
nil,
174 :max_files => get_number('g:CommandTMaxFiles'),
175 :max_depth => get_number('g:CommandTMaxDepth'),
176 :always_show_dot_files => get_bool('g:CommandTAlwaysShowDotFiles'),
177 :never_show_dot_files => get_bool('g:CommandTNeverShowDotFiles'),
178 :scan_dot_directories => get_bool('g:CommandTScanDotDirectories')
182 ::VIM::evaluate("exists(\"#{name}\")").to_i !
= 0
186 exists
?(name
) ? ::VIM::evaluate("#{name}").to_i
: nil
190 exists
?(name
) ? ::VIM::evaluate("#{name}").to_i !
= 0 : nil
194 exists
?(name
) ? ::VIM::evaluate("#{name}").to_s
: nil
197 # expect a string or a list of strings
198 def get_list_or_string name
199 return nil unless exists
?(name
)
200 list_or_string
= ::VIM::evaluate("#{name}")
201 if list_or_string
.kind_of
?(Array
)
202 list_or_string
.map
{ |item
| item
.to_s
}
208 # Backslash-escape space, \, |, %, #, "
209 def sanitize_path_string str
210 # for details on escaping command-line mode arguments see: :h :
211 # (that is, help on ":") in the Vim documentation.
212 str
.gsub(/[ \\|%#"]/, '\\\\\0')
215 def default_open_command
216 if !
get_bool('&hidden') && get_bool('&modified')
223 def ensure_appropriate_window_selection
224 # normally we try to open the selection in the current window, but there
227 # - we don't touch any "unlisted" buffer with buftype "nofile" (such as
228 # NERDTree or MiniBufExplorer); this is to avoid things like the "Not
229 # enough room" error which occurs when trying to open in a split in a
230 # shallow (potentially 1-line) buffer like MiniBufExplorer is current
232 # Other "unlisted" buffers, such as those with buftype "help" are treated
236 break unless ::VIM::evaluate('&buflisted').to_i
== 0 &&
237 ::VIM::evaluate('&buftype').to_s
== 'nofile'
238 ::VIM::command 'wincmd w' # try next window
239 break if $curwin == initial
# have already tried all
243 def open_selection selection
, options
= {}
244 command
= options
[:command] || default_open_command
245 selection
= File
.expand_path selection
, @path
246 selection
= relative_path_under_working_directory selection
247 selection
= sanitize_path_string selection
248 ensure_appropriate_window_selection
249 ::VIM::command "silent #{command} #{selection}"
252 def map key
, function
, param
= nil
253 ::VIM::command "noremap <silent> <buffer> #{key} " \
254 ":call CommandT#{function}(#{param})<CR>"
258 !!
(::VIM::evaluate('&term') =~
/\Axterm/)
262 !!
(::VIM::evaluate('&term') =~
/\Avt100/)
265 def register_for_key_presses
266 # "normal" keys (interpreted literally)
267 numbers
= ('0'..'9').to_a
.join
268 lowercase
= ('a'..'z').to_a
.join
269 uppercase
= lowercase
.upcase
270 punctuation
= '<>`@#~!"$%&/()=+*-_
.,;:?\\\'{}[] ' # and space
271 (numbers + lowercase + uppercase + punctuation
).each_byte
do |b
|
272 map
"<Char-#{b}>", 'HandleKey', b
275 # "special" keys (overridable by settings)
276 { 'Backspace' => '<BS>',
278 'AcceptSelection' => '<CR>',
279 'AcceptSelectionSplit' => ['<C-CR>', '<C-s>'],
280 'AcceptSelectionTab' => '<C-t>',
281 'AcceptSelectionVSplit' => '<C-v>',
282 'ToggleFocus' => '<Tab>',
283 'Cancel' => ['<C-c>', '<Esc>'],
284 'SelectNext' => ['<C-n>', '<C-j>', '<Down>'],
285 'SelectPrev' => ['<C-p>', '<C-k>', '<Up>'],
287 'CursorLeft' => ['<Left>', '<C-h>'],
288 'CursorRight' => ['<Right>', '<C-l>'],
289 'CursorEnd' => '<C-e>',
290 'CursorStart' => '<C-a>' }.each
do |key
, value
|
291 if override
= get_list_or_string("g:CommandT#{key}Map")
292 [override
].flatten
.each
do |mapping
|
296 [value
].flatten
.each
do |mapping
|
297 map mapping
, key
unless mapping
== '<Esc>' && (xterm
? || vt100
?)
303 # Returns the desired maximum number of matches, based on available
304 # vertical space and the g:CommandTMaxHeight option.
306 limit
= VIM
::Screen.lines
- 5
307 limit
= 1 if limit
< 0
308 limit
= [limit
, @max_height].min
if @max_height > 0
313 matches
= @active_finder.sorted_matches_for
@prompt.abbrev
, :limit => match_limit
314 @match_window.matches
= matches
316 end # class Controller
317 end # module commandT