command-t 1.6.1 → 1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- # Copyright 2010-2013 Wincent Colaiuta. All rights reserved.
1
+ # Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
2
2
  #
3
3
  # Redistribution and use in source and binary forms, with or without
4
4
  # modification, are permitted provided that the following conditions are met:
@@ -47,17 +47,16 @@ module CommandT
47
47
  :width => ::VIM::Window[i].width)
48
48
  end
49
49
 
50
- # global settings (must manually save and restore)
51
- @settings = Settings.new
52
- ::VIM::set_option 'timeout' # ensure mappings timeout
53
- ::VIM::set_option 'timeoutlen=0' # respond immediately to mappings
54
- ::VIM::set_option 'nohlsearch' # don't highlight search strings
55
- ::VIM::set_option 'noinsertmode' # don't make Insert mode the default
56
- ::VIM::set_option 'noshowcmd' # don't show command info on last line
57
- ::VIM::set_option 'report=9999' # don't show "X lines changed" reports
58
- ::VIM::set_option 'sidescroll=0' # don't sidescroll in jumps
59
- ::VIM::set_option 'sidescrolloff=0' # don't sidescroll automatically
60
- ::VIM::set_option 'noequalalways' # don't auto-balance window sizes
50
+ set 'timeout', true # ensure mappings timeout
51
+ set 'hlsearch', false # don't highlight search strings
52
+ set 'insertmode', false # don't make Insert mode the default
53
+ set 'showcmd', false # don't show command info on last line
54
+ set 'equalalways', false # don't auto-balance window sizes
55
+ set 'timeoutlen', 0 # respond immediately to mappings
56
+ set 'report', 9999 # don't show "X lines changed" reports
57
+ set 'sidescroll', 0 # don't sidescroll in jumps
58
+ set 'sidescrolloff', 0 # don't sidescroll automatically
59
+ set 'updatetime', options[:debounce_interval]
61
60
 
62
61
  # show match window
63
62
  split_location = options[:match_window_at_top] ? 'topleft' : 'botright'
@@ -66,29 +65,26 @@ module CommandT
66
65
  raise "Can't re-open GoToFile buffer" unless $curbuf.number == @@buffer.number
67
66
  $curwin.height = 1
68
67
  else # creating match window for first time and set it up
69
- split_command = "silent! #{split_location} 1split GoToFile"
70
- [
71
- split_command,
72
- 'setlocal bufhidden=unload', # unload buf when no longer displayed
73
- 'setlocal buftype=nofile', # buffer is not related to any file
74
- 'setlocal nomodifiable', # prevent manual edits
75
- 'setlocal noswapfile', # don't create a swapfile
76
- 'setlocal nowrap', # don't soft-wrap
77
- 'setlocal nonumber', # don't show line numbers
78
- 'setlocal nolist', # don't use List mode (visible tabs etc)
79
- 'setlocal foldcolumn=0', # don't show a fold column at side
80
- 'setlocal foldlevel=99', # don't fold anything
81
- 'setlocal nocursorline', # don't highlight line cursor is on
82
- 'setlocal nospell', # spell-checking off
83
- 'setlocal nobuflisted', # don't show up in the buffer list
84
- 'setlocal textwidth=0' # don't hard-wrap (break long lines)
85
- ].each { |command| ::VIM::command command }
68
+ ::VIM::command "silent! #{split_location} 1split GoToFile"
69
+ set 'bufhidden', 'unload' # unload buf when no longer displayed
70
+ set 'buftype', 'nofile' # buffer is not related to any file
71
+ set 'modifiable', false # prevent manual edits
72
+ set 'swapfile', false # don't create a swapfile
73
+ set 'wrap', false # don't soft-wrap
74
+ set 'number', false # don't show line numbers
75
+ set 'list', false # don't use List mode (visible tabs etc)
76
+ set 'foldcolumn', 0 # don't show a fold column at side
77
+ set 'foldlevel', 99 # don't fold anything
78
+ set 'cursorline', false # don't highlight line cursor is on
79
+ set 'spell', false # spell-checking off
80
+ set 'buflisted', false # don't show up in the buffer list
81
+ set 'textwidth', 0 # don't hard-wrap (break long lines)
86
82
 
87
83
  # don't show the color column
88
- ::VIM::command 'setlocal colorcolumn=0' if VIM::exists?('+colorcolumn')
84
+ set 'colorcolumn', 0 if VIM::exists?('+colorcolumn')
89
85
 
90
86
  # don't show relative line numbers
91
- ::VIM::command 'setlocal norelativenumber' if VIM::exists?('+relativenumber')
87
+ set 'relativenumber', false if VIM::exists?('+relativenumber')
92
88
 
93
89
  # sanity check: make sure the buffer really was created
94
90
  raise "Can't find GoToFile buffer" unless $curbuf.name.match /GoToFile\z/
@@ -100,11 +96,11 @@ module CommandT
100
96
  ::VIM::command "syntax match CommandTSelection \"^#{SELECTION_MARKER}.\\+$\""
101
97
  ::VIM::command 'syntax match CommandTNoEntries "^-- NO MATCHES --$"'
102
98
  ::VIM::command 'syntax match CommandTNoEntries "^-- NO SUCH FILE OR DIRECTORY --$"'
103
- ::VIM::command 'setlocal synmaxcol=9999'
99
+ set 'synmaxcol', 9999
104
100
 
105
101
  if VIM::has_conceal?
106
- ::VIM::command 'setlocal conceallevel=2'
107
- ::VIM::command 'setlocal concealcursor=nvic'
102
+ set 'conceallevel', 2
103
+ set 'concealcursor', 'nvic'
108
104
  ::VIM::command 'syntax region CommandTCharMatched ' \
109
105
  "matchgroup=CommandTCharMatched start=+#{MH_START}+ " \
110
106
  "matchgroup=CommandTCharMatchedEnd end=+#{MH_END}+ concealends"
@@ -115,7 +111,6 @@ module CommandT
115
111
 
116
112
  ::VIM::command "highlight link CommandTSelection #{@highlight_color}"
117
113
  ::VIM::command 'highlight link CommandTNoEntries Error'
118
- ::VIM::evaluate 'clearmatches()'
119
114
 
120
115
  # hide cursor
121
116
  @cursor_highlight = get_cursor_highlight
@@ -266,6 +261,11 @@ module CommandT
266
261
 
267
262
  private
268
263
 
264
+ def set(setting, value)
265
+ @settings ||= Settings.new
266
+ @settings.set(setting, value)
267
+ end
268
+
269
269
  def move_cursor_to_selected_line
270
270
  # on some non-GUI terminals, the cursor doesn't hide properly
271
271
  # so we move the cursor to prevent it from blinking away in the
@@ -436,11 +436,11 @@ module CommandT
436
436
  end
437
437
 
438
438
  def lock
439
- ::VIM::command 'setlocal nomodifiable'
439
+ set 'modifiable', false
440
440
  end
441
441
 
442
442
  def unlock
443
- ::VIM::command 'setlocal modifiable'
443
+ set 'modifiable', true
444
444
  end
445
445
  end
446
446
  end
@@ -1,4 +1,4 @@
1
- # Copyright 2010-2013 Wincent Colaiuta. All rights reserved.
1
+ # Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
2
2
  #
3
3
  # Redistribution and use in source and binary forms, with or without
4
4
  # modification, are permitted provided that the following conditions are met:
@@ -26,11 +26,15 @@ require 'command-t/scanner'
26
26
 
27
27
  module CommandT
28
28
  # Reads the current directory recursively for the paths to all regular files.
29
+ #
30
+ # This is an abstract superclass; the real work is done by subclasses which
31
+ # obtain file listings via different strategies (for examples, see the
32
+ # RubyFileScanner and FindFileScanner subclasses).
29
33
  class FileScanner < Scanner
30
34
  class FileLimitExceeded < ::RuntimeError; end
31
35
  attr_accessor :path
32
36
 
33
- def initialize path = Dir.pwd, options = {}
37
+ def initialize(path = Dir.pwd, options = {})
34
38
  @paths = {}
35
39
  @paths_keys = []
36
40
  @path = path
@@ -43,20 +47,11 @@ module CommandT
43
47
  end
44
48
 
45
49
  def paths
46
- return @paths[@path] if @paths.has_key?(@path)
47
- begin
50
+ @paths[@path] || begin
48
51
  ensure_cache_under_limit
49
- @paths[@path] = []
50
- @depth = 0
51
- @files = 0
52
- @prefix_len = @path.chomp('/').length
53
- set_wild_ignore(@wild_ignore)
54
- add_paths_for_directory @path, @paths[@path]
55
- rescue FileLimitExceeded
56
- ensure
57
- set_wild_ignore(@base_wild_ignore)
52
+ @prefix_len = @path.chomp('/').length
53
+ nil
58
54
  end
59
- @paths[@path]
60
55
  end
61
56
 
62
57
  def flush
@@ -74,45 +69,15 @@ module CommandT
74
69
  @paths_keys << @path
75
70
  end
76
71
 
77
- def path_excluded? path
72
+ def path_excluded?(path)
78
73
  # first strip common prefix (@path) from path to match VIM's behavior
79
74
  path = path[(@prefix_len + 1)..-1]
80
75
  path = VIM::escape_for_single_quotes path
81
76
  ::VIM::evaluate("empty(expand(fnameescape('#{path}')))").to_i == 1
82
77
  end
83
78
 
84
- def looped_symlink? path
85
- if File.symlink?(path)
86
- target = File.expand_path(File.readlink(path), File.dirname(path))
87
- target.include?(@path) || @path.include?(target)
88
- end
89
- end
90
-
91
79
  def set_wild_ignore(ignore)
92
80
  ::VIM::command("set wildignore=#{ignore}") if @wild_ignore
93
81
  end
94
-
95
- def add_paths_for_directory dir, accumulator
96
- Dir.foreach(dir) do |entry|
97
- next if ['.', '..'].include?(entry)
98
- path = File.join(dir, entry)
99
- unless path_excluded?(path)
100
- if File.file?(path)
101
- @files += 1
102
- raise FileLimitExceeded if @files > @max_files
103
- accumulator << path[@prefix_len + 1..-1]
104
- elsif File.directory?(path)
105
- next if @depth >= @max_depth
106
- next if (entry.match(/\A\./) && !@scan_dot_directories)
107
- next if looped_symlink?(path)
108
- @depth += 1
109
- add_paths_for_directory path, accumulator
110
- @depth -= 1
111
- end
112
- end
113
- end
114
- rescue Errno::EACCES
115
- # skip over directories for which we don't have access
116
- end
117
82
  end # class FileScanner
118
83
  end # module CommandT
@@ -0,0 +1,77 @@
1
+ # Copyright 2014 Wincent Colaiuta. All rights reserved.
2
+ #
3
+ # Redistribution and use in source and binary forms, with or without
4
+ # modification, are permitted provided that the following conditions are met:
5
+ #
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.
11
+ #
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.
23
+
24
+ require 'open3'
25
+ require 'command-t/vim'
26
+ require 'command-t/vim/path_utilities'
27
+ require 'command-t/scanner/file_scanner'
28
+
29
+ module CommandT
30
+ class FileScanner
31
+ # A FileScanner which shells out to the `find` executable in order to scan.
32
+ class FindFileScanner < FileScanner
33
+ include VIM::PathUtilities
34
+
35
+ def paths
36
+ super || begin
37
+ set_wild_ignore(@wild_ignore)
38
+
39
+ # temporarily set field separator to NUL byte; this setting is
40
+ # respected by both `readlines` and `chomp!` below, and makes it easier
41
+ # to parse the output of `find -print0`
42
+ separator = $/
43
+ $/ = "\x00"
44
+
45
+ unless @scan_dot_directories
46
+ dot_directory_filter = [
47
+ '-not', '-path', "#{@path}/.*/*", # top-level dot dir
48
+ '-and', '-not', '-path', "#{@path}/*/.*/*" # lower-level dot dir
49
+ ]
50
+ end
51
+
52
+ Open3.popen3(*([
53
+ 'find', '-L', # follow symlinks
54
+ @path, # anchor search here
55
+ '-maxdepth', @max_depth.to_s, # limit depth of DFS
56
+ '-type', 'f', # only show regular files (not dirs etc)
57
+ dot_directory_filter, # possibly skip out dot directories
58
+ '-print0' # NUL-terminate results
59
+ ].flatten.compact)) do |stdin, stdout, stderr|
60
+ counter = 1
61
+ paths = []
62
+ stdout.readlines.each do |line|
63
+ next if path_excluded?(line.chomp!)
64
+ paths << line[@prefix_len + 1..-1]
65
+ break if (counter += 1) > @max_files
66
+ end
67
+ @paths[@path] = paths
68
+ end
69
+ ensure
70
+ $/ = separator
71
+ set_wild_ignore(@base_wild_ignore)
72
+ end
73
+ @paths[@path]
74
+ end
75
+ end # class FindFileScanner
76
+ end # class FileScanner
77
+ end # module CommandT
@@ -0,0 +1,78 @@
1
+ # Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
2
+ #
3
+ # Redistribution and use in source and binary forms, with or without
4
+ # modification, are permitted provided that the following conditions are met:
5
+ #
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.
11
+ #
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.
23
+
24
+ require 'command-t/vim'
25
+ require 'command-t/scanner/file_scanner'
26
+
27
+ module CommandT
28
+ class FileScanner
29
+ # Pure Ruby implementation of a file scanner.
30
+ class RubyFileScanner < FileScanner
31
+ def paths
32
+ super || begin
33
+ @paths[@path] = []
34
+ @depth = 0
35
+ @files = 0
36
+ set_wild_ignore(@wild_ignore)
37
+ add_paths_for_directory @path, @paths[@path]
38
+ rescue FileLimitExceeded
39
+ ensure
40
+ set_wild_ignore(@base_wild_ignore)
41
+ end
42
+ @paths[@path]
43
+ end
44
+
45
+ private
46
+
47
+ def looped_symlink? path
48
+ if File.symlink?(path)
49
+ target = File.expand_path(File.readlink(path), File.dirname(path))
50
+ target.include?(@path) || @path.include?(target)
51
+ end
52
+ end
53
+
54
+ def add_paths_for_directory dir, accumulator
55
+ Dir.foreach(dir) do |entry|
56
+ next if ['.', '..'].include?(entry)
57
+ path = File.join(dir, entry)
58
+ unless path_excluded?(path)
59
+ if File.file?(path)
60
+ @files += 1
61
+ raise FileLimitExceeded if @files > @max_files
62
+ accumulator << path[@prefix_len + 1..-1]
63
+ elsif File.directory?(path)
64
+ next if @depth >= @max_depth
65
+ next if (entry.match(/\A\./) && !@scan_dot_directories)
66
+ next if looped_symlink?(path)
67
+ @depth += 1
68
+ add_paths_for_directory path, accumulator
69
+ @depth -= 1
70
+ end
71
+ end
72
+ end
73
+ rescue Errno::EACCES
74
+ # skip over directories for which we don't have access
75
+ end
76
+ end # class RubyFileScanner
77
+ end # class FileScanner
78
+ end # module CommandT
@@ -0,0 +1,79 @@
1
+ # Copyright 2014 Wincent Colaiuta. All rights reserved.
2
+ #
3
+ # Redistribution and use in source and binary forms, with or without
4
+ # modification, are permitted provided that the following conditions are met:
5
+ #
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.
11
+ #
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.
23
+
24
+ require 'json'
25
+ require 'socket'
26
+ require 'command-t/vim'
27
+ require 'command-t/vim/path_utilities'
28
+ require 'command-t/scanner/file_scanner'
29
+ require 'command-t/scanner/file_scanner/find_file_scanner'
30
+
31
+ module CommandT
32
+ class FileScanner
33
+ # A FileScanner which delegates the heavy lifting to Watchman
34
+ # (https://github.com/facebook/watchman); useful for very large hierarchies.
35
+ #
36
+ # Inherits from FindFileScanner so that it can fall back to it in the event
37
+ # that Watchman isn't available or able to fulfil the request.
38
+ class WatchmanFileScanner < FindFileScanner
39
+ # Exception raised when Watchman is unavailable or unable to process the
40
+ # requested path.
41
+ class WatchmanUnavailable < RuntimeError; end
42
+
43
+ def paths
44
+ @paths[@path] ||= begin
45
+ ensure_cache_under_limit
46
+ sockname = JSON[%x{watchman get-sockname}]['sockname']
47
+ raise WatchmanUnavailable unless $?.exitstatus.zero?
48
+ socket = UNIXSocket.open(sockname) do |s|
49
+ root = File.realpath(File.expand_path(@path))
50
+ s.puts JSON.generate(['watch-list'])
51
+ if !JSON[s.gets]['roots'].include?(root)
52
+ # this path isn't being watched yet; try to set up watch
53
+ s.puts JSON.generate(['watch', root])
54
+
55
+ # root_restrict_files setting may prevent Watchman from working
56
+ raise WatchmanUnavailable if JSON[s.gets].has_key?('error')
57
+ end
58
+
59
+ s.puts JSON.generate(['query', root, {
60
+ 'expression' => ['type', 'f'],
61
+ 'fields' => ['name'],
62
+ }])
63
+ paths = JSON[s.gets]
64
+
65
+ # could return error if watch is removed
66
+ raise WatchmanUnavailable if paths.has_key?('error')
67
+
68
+ @paths[@path] = paths['files']
69
+ end
70
+ end
71
+
72
+ @paths[@path]
73
+ rescue Errno::ENOENT, WatchmanUnavailable
74
+ # watchman executable not present, or unable to fulfil request
75
+ super
76
+ end
77
+ end # class WatchmanFileScanner
78
+ end # class FileScanner
79
+ end # module CommandT