command-t 1.11 → 1.11.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.txt +53 -12
- data/Rakefile +2 -2
- data/doc/command-t.txt +53 -12
- data/ruby/command-t/controller.rb +34 -56
- data/ruby/command-t/ext.bundle +0 -0
- data/ruby/command-t/extconf.rb +1 -0
- data/ruby/command-t/finder.rb +4 -4
- data/ruby/command-t/finder/mru_buffer_finder.rb +8 -8
- data/ruby/command-t/finder/tag_finder.rb +2 -2
- data/ruby/command-t/match.c +8 -19
- data/ruby/command-t/match_window.rb +15 -15
- data/ruby/command-t/mru.rb +5 -0
- data/ruby/command-t/prompt.rb +18 -18
- data/ruby/command-t/scanner/buffer_scanner.rb +0 -1
- data/ruby/command-t/scanner/file_scanner.rb +30 -16
- data/ruby/command-t/scanner/file_scanner/find_file_scanner.rb +29 -36
- data/ruby/command-t/scanner/file_scanner/git_file_scanner.rb +18 -25
- data/ruby/command-t/scanner/file_scanner/ruby_file_scanner.rb +12 -17
- data/ruby/command-t/scanner/file_scanner/watchman_file_scanner.rb +29 -35
- data/ruby/command-t/scanner/jump_scanner.rb +1 -2
- data/ruby/command-t/scanner/tag_scanner.rb +1 -2
- data/ruby/command-t/settings.rb +5 -15
- data/ruby/command-t/stub.rb +3 -2
- data/ruby/command-t/vim.rb +53 -29
- data/ruby/command-t/vim/path_utilities.rb +1 -1
- data/ruby/command-t/vim/screen.rb +4 -2
- data/ruby/command-t/vim/window.rb +11 -9
- metadata +2 -2
data/ruby/command-t/ext.bundle
CHANGED
Binary file
|
data/ruby/command-t/extconf.rb
CHANGED
@@ -21,6 +21,7 @@ if have_header('fcntl.h') &&
|
|
21
21
|
have_header('stdint.h') &&
|
22
22
|
have_header('sys/errno.h') &&
|
23
23
|
have_header('sys/socket.h')
|
24
|
+
RbConfig::MAKEFILE_CONFIG['DEFS'] ||= ''
|
24
25
|
RbConfig::MAKEFILE_CONFIG['DEFS'] += ' -DWATCHMAN_BUILD'
|
25
26
|
|
26
27
|
have_header('ruby/st.h') # >= 1.9; sets HAVE_RUBY_ST_H
|
data/ruby/command-t/finder.rb
CHANGED
@@ -13,21 +13,21 @@ module CommandT
|
|
13
13
|
class Finder
|
14
14
|
include VIM::PathUtilities
|
15
15
|
|
16
|
-
def initialize
|
16
|
+
def initialize(path = Dir.pwd, options = {})
|
17
17
|
raise RuntimeError, 'Subclass responsibility'
|
18
18
|
end
|
19
19
|
|
20
20
|
# Options:
|
21
21
|
# :limit (integer): limit the number of returned matches
|
22
|
-
def sorted_matches_for
|
22
|
+
def sorted_matches_for(str, options = {})
|
23
23
|
@matcher.sorted_matches_for str, options
|
24
24
|
end
|
25
25
|
|
26
|
-
def open_selection
|
26
|
+
def open_selection(command, selection, options = {})
|
27
27
|
::VIM::command "silent #{command} #{selection}"
|
28
28
|
end
|
29
29
|
|
30
|
-
def path=
|
30
|
+
def path=(path)
|
31
31
|
@scanner.path = path
|
32
32
|
end
|
33
33
|
end # class Finder
|
@@ -7,24 +7,24 @@ require 'command-t/finder/buffer_finder'
|
|
7
7
|
|
8
8
|
module CommandT
|
9
9
|
class MRUBufferFinder < BufferFinder
|
10
|
+
def initialize
|
11
|
+
@scanner = MRUBufferScanner.new
|
12
|
+
@matcher = Matcher.new @scanner, :always_show_dot_files => true
|
13
|
+
end
|
14
|
+
|
10
15
|
# Override sorted_matches_for to prevent MRU ordered matches from being
|
11
16
|
# ordered alphabetically.
|
12
|
-
def sorted_matches_for
|
17
|
+
def sorted_matches_for(str, options = {})
|
13
18
|
matches = super(str, options.merge(:sort => false))
|
14
19
|
|
15
20
|
# take current buffer (by definition, the most recently used) and move it
|
16
21
|
# to the end of the results
|
17
|
-
if MRU.
|
18
|
-
relative_path_under_working_directory(MRU.
|
22
|
+
if MRU.last &&
|
23
|
+
relative_path_under_working_directory(MRU.last.name) == matches.first
|
19
24
|
matches[1..-1] + [matches.first]
|
20
25
|
else
|
21
26
|
matches
|
22
27
|
end
|
23
28
|
end
|
24
|
-
|
25
|
-
def initialize
|
26
|
-
@scanner = MRUBufferScanner.new
|
27
|
-
@matcher = Matcher.new @scanner, :always_show_dot_files => true
|
28
|
-
end
|
29
29
|
end # class MRUBufferFinder
|
30
30
|
end # CommandT
|
@@ -7,12 +7,12 @@ require 'command-t/finder'
|
|
7
7
|
|
8
8
|
module CommandT
|
9
9
|
class TagFinder < Finder
|
10
|
-
def initialize
|
10
|
+
def initialize(options = {})
|
11
11
|
@scanner = TagScanner.new options
|
12
12
|
@matcher = Matcher.new @scanner, :always_show_dot_files => true
|
13
13
|
end
|
14
14
|
|
15
|
-
def open_selection
|
15
|
+
def open_selection(command, selection, options = {})
|
16
16
|
if @scanner.include_filenames
|
17
17
|
selection = selection[0, selection.index(':')]
|
18
18
|
end
|
data/ruby/command-t/match.c
CHANGED
@@ -13,7 +13,6 @@ typedef struct {
|
|
13
13
|
char *needle_p; // pointer to search string (needle)
|
14
14
|
long needle_len; // length of same
|
15
15
|
double max_score_per_char;
|
16
|
-
int dot_file; // boolean: true if str is a dot-file
|
17
16
|
int always_show_dot_files; // boolean
|
18
17
|
int never_show_dot_files; // boolean
|
19
18
|
int case_sensitive; // boolean
|
@@ -26,12 +25,10 @@ double recursive_match(matchinfo_t *m, // sharable meta-data
|
|
26
25
|
long last_idx, // location of last matched character
|
27
26
|
double score) // cumulative score so far
|
28
27
|
{
|
28
|
+
double score_for_char;
|
29
29
|
double seen_score = 0; // remember best score seen via recursion
|
30
|
-
int dot_file_match = 0; // true if needle matches a dot-file
|
31
|
-
int dot_search = 0; // true if searching for a dot
|
32
|
-
long i, j, distance;
|
33
30
|
int found;
|
34
|
-
|
31
|
+
long i, j, distance;
|
35
32
|
long memo_idx = haystack_idx;
|
36
33
|
|
37
34
|
// do we have a memoized result we can return?
|
@@ -47,8 +44,6 @@ double recursive_match(matchinfo_t *m, // sharable meta-data
|
|
47
44
|
|
48
45
|
for (i = needle_idx; i < m->needle_len; i++) {
|
49
46
|
char c = m->needle_p[i];
|
50
|
-
if (c == '.')
|
51
|
-
dot_search = 1;
|
52
47
|
found = 0;
|
53
48
|
|
54
49
|
// similar to above, we'll stop iterating when we know we're too close
|
@@ -58,10 +53,12 @@ double recursive_match(matchinfo_t *m, // sharable meta-data
|
|
58
53
|
j++, haystack_idx++) {
|
59
54
|
char d = m->haystack_p[j];
|
60
55
|
if (d == '.') {
|
61
|
-
if (j == 0 || m->haystack_p[j - 1] == '/') {
|
62
|
-
|
63
|
-
if (
|
64
|
-
|
56
|
+
if (j == 0 || m->haystack_p[j - 1] == '/') { // this is a dot-file
|
57
|
+
int dot_search = (i == 0 && c == '.'); // searching for a dot
|
58
|
+
if (m->never_show_dot_files || (!dot_search && !m->always_show_dot_files)) {
|
59
|
+
score = 0.0;
|
60
|
+
goto memoize;
|
61
|
+
}
|
65
62
|
}
|
66
63
|
} else if (d >= 'A' && d <= 'Z' && !m->case_sensitive) {
|
67
64
|
d += 'a' - 'A'; // add 32 to downcase
|
@@ -69,7 +66,6 @@ double recursive_match(matchinfo_t *m, // sharable meta-data
|
|
69
66
|
|
70
67
|
if (c == d) {
|
71
68
|
found = 1;
|
72
|
-
dot_search = 0;
|
73
69
|
|
74
70
|
// calculate score
|
75
71
|
score_for_char = m->max_score_per_char;
|
@@ -117,12 +113,6 @@ double recursive_match(matchinfo_t *m, // sharable meta-data
|
|
117
113
|
}
|
118
114
|
}
|
119
115
|
|
120
|
-
if (m->dot_file &&
|
121
|
-
(m->never_show_dot_files ||
|
122
|
-
(!dot_file_match && !m->always_show_dot_files))) {
|
123
|
-
score = 0.0;
|
124
|
-
goto memoize;
|
125
|
-
}
|
126
116
|
score = score > seen_score ? score : seen_score;
|
127
117
|
|
128
118
|
memoize:
|
@@ -145,7 +135,6 @@ void calculate_match(VALUE str,
|
|
145
135
|
m.needle_p = RSTRING_PTR(needle);
|
146
136
|
m.needle_len = RSTRING_LEN(needle);
|
147
137
|
m.max_score_per_char = (1.0 / m.haystack_len + 1.0 / m.needle_len) / 2;
|
148
|
-
m.dot_file = 0;
|
149
138
|
m.always_show_dot_files = always_show_dot_files == Qtrue;
|
150
139
|
m.never_show_dot_files = never_show_dot_files == Qtrue;
|
151
140
|
m.case_sensitive = case_sensitive;
|
@@ -13,7 +13,7 @@ module CommandT
|
|
13
13
|
MH_END = '</commandt>'
|
14
14
|
@@buffer = nil
|
15
15
|
|
16
|
-
def initialize
|
16
|
+
def initialize(options = {})
|
17
17
|
@highlight_color = options[:highlight_color] || 'PmenuSel'
|
18
18
|
@min_height = options[:min_height]
|
19
19
|
@prompt = options[:prompt]
|
@@ -74,13 +74,13 @@ module CommandT
|
|
74
74
|
end
|
75
75
|
|
76
76
|
# syntax coloring
|
77
|
-
if VIM::
|
77
|
+
if VIM::has?('syntax')
|
78
78
|
::VIM::command "syntax match CommandTSelection \"^#{SELECTION_MARKER}.\\+$\""
|
79
79
|
::VIM::command 'syntax match CommandTNoEntries "^-- NO MATCHES --$"'
|
80
80
|
::VIM::command 'syntax match CommandTNoEntries "^-- NO SUCH FILE OR DIRECTORY --$"'
|
81
81
|
set 'synmaxcol', 9999
|
82
82
|
|
83
|
-
if VIM::
|
83
|
+
if VIM::has?('conceal')
|
84
84
|
set 'conceallevel', 2
|
85
85
|
set 'concealcursor', 'nvic'
|
86
86
|
::VIM::command 'syntax region CommandTCharMatched ' \
|
@@ -151,7 +151,7 @@ module CommandT
|
|
151
151
|
show_cursor
|
152
152
|
end
|
153
153
|
|
154
|
-
def add!
|
154
|
+
def add!(char)
|
155
155
|
@abbrev += char
|
156
156
|
end
|
157
157
|
|
@@ -167,7 +167,7 @@ module CommandT
|
|
167
167
|
@reverse_list ? _next : _prev
|
168
168
|
end
|
169
169
|
|
170
|
-
def matches=
|
170
|
+
def matches=(matches)
|
171
171
|
if matches != @matches
|
172
172
|
@matches = matches
|
173
173
|
@selection = 0
|
@@ -179,7 +179,7 @@ module CommandT
|
|
179
179
|
def focus
|
180
180
|
unless @has_focus
|
181
181
|
@has_focus = true
|
182
|
-
if VIM::
|
182
|
+
if VIM::has?('syntax')
|
183
183
|
::VIM::command 'highlight link CommandTSelection Search'
|
184
184
|
end
|
185
185
|
end
|
@@ -188,7 +188,7 @@ module CommandT
|
|
188
188
|
def unfocus
|
189
189
|
if @has_focus
|
190
190
|
@has_focus = false
|
191
|
-
if VIM::
|
191
|
+
if VIM::has?('syntax')
|
192
192
|
::VIM::command "highlight link CommandTSelection #{@highlight_color}"
|
193
193
|
end
|
194
194
|
end
|
@@ -264,7 +264,7 @@ module CommandT
|
|
264
264
|
@window.cursor = [line(@selection), 0]
|
265
265
|
end
|
266
266
|
|
267
|
-
def print_error
|
267
|
+
def print_error(msg)
|
268
268
|
return unless VIM::Window.select(@window)
|
269
269
|
unlock
|
270
270
|
clear
|
@@ -296,13 +296,13 @@ module CommandT
|
|
296
296
|
end
|
297
297
|
end
|
298
298
|
|
299
|
-
def match_text_for_idx
|
299
|
+
def match_text_for_idx(idx)
|
300
300
|
match = truncated_match @matches[idx].to_s
|
301
301
|
if idx == @selection
|
302
302
|
prefix = SELECTION_MARKER
|
303
303
|
suffix = padding_for_selected_match match
|
304
304
|
else
|
305
|
-
if VIM::
|
305
|
+
if VIM::has?('syntax') && VIM::has?('conceal')
|
306
306
|
match = match_with_syntax_highlight match
|
307
307
|
end
|
308
308
|
prefix = UNSELECTED_MARKER
|
@@ -318,9 +318,9 @@ module CommandT
|
|
318
318
|
# were used by the matching/scoring algorithm to determine the best score
|
319
319
|
# for the match.
|
320
320
|
#
|
321
|
-
def match_with_syntax_highlight
|
322
|
-
highlight_chars = @prompt.abbrev.downcase.
|
323
|
-
match.
|
321
|
+
def match_with_syntax_highlight(match)
|
322
|
+
highlight_chars = @prompt.abbrev.downcase.scan(/./mu)
|
323
|
+
match.scan(/./mu).inject([]) do |output, char|
|
324
324
|
if char.downcase == highlight_chars.first
|
325
325
|
highlight_chars.shift
|
326
326
|
output.concat [MH_START, char, MH_END]
|
@@ -373,7 +373,7 @@ module CommandT
|
|
373
373
|
|
374
374
|
# Prepare padding for match text (trailing spaces) so that selection
|
375
375
|
# highlighting extends all the way to the right edge of the window.
|
376
|
-
def padding_for_selected_match
|
376
|
+
def padding_for_selected_match(str)
|
377
377
|
len = str.length
|
378
378
|
if len >= @window_width - MARKER_LENGTH
|
379
379
|
''
|
@@ -384,7 +384,7 @@ module CommandT
|
|
384
384
|
|
385
385
|
# Convert "really/long/path" into "really...path" based on available
|
386
386
|
# window width.
|
387
|
-
def truncated_match
|
387
|
+
def truncated_match(str)
|
388
388
|
len = str.length
|
389
389
|
available_width = @window_width - MARKER_LENGTH
|
390
390
|
return str if len <= available_width
|
data/ruby/command-t/mru.rb
CHANGED
data/ruby/command-t/prompt.rb
CHANGED
@@ -43,7 +43,7 @@ module CommandT
|
|
43
43
|
end
|
44
44
|
|
45
45
|
# Insert a character at (before) the current cursor position.
|
46
|
-
def add!
|
46
|
+
def add!(char)
|
47
47
|
left, cursor, right = abbrev_segments
|
48
48
|
@abbrev = left + char + cursor + right
|
49
49
|
@col += 1
|
@@ -97,6 +97,22 @@ module CommandT
|
|
97
97
|
end
|
98
98
|
end
|
99
99
|
|
100
|
+
def focus
|
101
|
+
unless @has_focus
|
102
|
+
@has_focus = true
|
103
|
+
redraw
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def unfocus
|
108
|
+
if @has_focus
|
109
|
+
@has_focus = false
|
110
|
+
redraw
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
100
116
|
def redraw
|
101
117
|
if @has_focus
|
102
118
|
prompt_highlight = 'Comment'
|
@@ -116,22 +132,6 @@ module CommandT
|
|
116
132
|
set_status *components
|
117
133
|
end
|
118
134
|
|
119
|
-
def focus
|
120
|
-
unless @has_focus
|
121
|
-
@has_focus = true
|
122
|
-
redraw
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
def unfocus
|
127
|
-
if @has_focus
|
128
|
-
@has_focus = false
|
129
|
-
redraw
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
private
|
134
|
-
|
135
135
|
# Returns the @abbrev string divided up into three sections, any of
|
136
136
|
# which may actually be zero width, depending on the location of the
|
137
137
|
# cursor:
|
@@ -145,7 +145,7 @@ module CommandT
|
|
145
145
|
[left, cursor, right]
|
146
146
|
end
|
147
147
|
|
148
|
-
def set_status
|
148
|
+
def set_status(*args)
|
149
149
|
# see ':help :echo' for why forcing a redraw here helps
|
150
150
|
# prevent the status line from getting inadvertantly cleared
|
151
151
|
# after our echo commands
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# Copyright 2010-2014 Greg Hurrell. All rights reserved.
|
2
2
|
# Licensed under the terms of the BSD 2-clause license.
|
3
3
|
|
4
|
-
require 'command-t/vim'
|
5
4
|
require 'command-t/scanner'
|
6
5
|
|
7
6
|
module CommandT
|
@@ -23,18 +22,14 @@ module CommandT
|
|
23
22
|
@max_caches = options[:max_caches] || 1
|
24
23
|
@scan_dot_directories = options[:scan_dot_directories] || false
|
25
24
|
@wild_ignore = options[:wild_ignore]
|
26
|
-
@base_wild_ignore =
|
27
|
-
end
|
28
|
-
|
29
|
-
def prepare_paths
|
30
|
-
ensure_cache_under_limit
|
31
|
-
@prefix_len = @path.chomp('/').length
|
25
|
+
@base_wild_ignore = wild_ignore
|
32
26
|
end
|
33
27
|
|
34
28
|
def paths
|
35
|
-
@paths[@path]
|
36
|
-
|
37
|
-
|
29
|
+
@paths[@path] ||= begin
|
30
|
+
ensure_cache_under_limit
|
31
|
+
@prefix_len = @path.chomp('/').length + 1
|
32
|
+
set_wild_ignore { paths! }
|
38
33
|
end
|
39
34
|
end
|
40
35
|
|
@@ -44,6 +39,14 @@ module CommandT
|
|
44
39
|
|
45
40
|
private
|
46
41
|
|
42
|
+
def wild_ignore
|
43
|
+
VIM::exists?('&wildignore') && ::VIM::evaluate('&wildignore').to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
def paths!
|
47
|
+
raise RuntimeError, 'Subclass responsibility'
|
48
|
+
end
|
49
|
+
|
47
50
|
def ensure_cache_under_limit
|
48
51
|
# Ruby 1.8 doesn't have an ordered hash, so use a separate stack to
|
49
52
|
# track and expire the oldest entry in the cache
|
@@ -54,18 +57,29 @@ module CommandT
|
|
54
57
|
end
|
55
58
|
|
56
59
|
def path_excluded?(path, prefix_len = @prefix_len)
|
57
|
-
|
58
|
-
# expensive for large file lists
|
59
|
-
if @wild_ignore && !@wild_ignore.empty?
|
60
|
+
if apply_wild_ignore?
|
60
61
|
# first strip common prefix (@path) from path to match VIM's behavior
|
61
|
-
path = path[
|
62
|
+
path = path[prefix_len..-1]
|
62
63
|
path = VIM::escape_for_single_quotes path
|
63
64
|
::VIM::evaluate("empty(expand(fnameescape('#{path}')))").to_i == 1
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
67
|
-
def
|
68
|
-
|
68
|
+
def has_custom_wild_ignore?
|
69
|
+
@wild_ignore && !@wild_ignore.empty?
|
70
|
+
end
|
71
|
+
|
72
|
+
# Used to skip expensive calls to `expand()` when there is no applicable
|
73
|
+
# wildignore.
|
74
|
+
def apply_wild_ignore?
|
75
|
+
has_custom_wild_ignore? || @base_wild_ignore
|
76
|
+
end
|
77
|
+
|
78
|
+
def set_wild_ignore(&block)
|
79
|
+
::VIM::command("set wildignore=#{@wild_ignore}") if has_custom_wild_ignore?
|
80
|
+
yield
|
81
|
+
ensure
|
82
|
+
::VIM::command("set wildignore=#{@base_wild_ignore}") if has_custom_wild_ignore?
|
69
83
|
end
|
70
84
|
end # class FileScanner
|
71
85
|
end # module CommandT
|
@@ -2,7 +2,6 @@
|
|
2
2
|
# Licensed under the terms of the BSD 2-clause license.
|
3
3
|
|
4
4
|
require 'open3'
|
5
|
-
require 'command-t/vim'
|
6
5
|
require 'command-t/vim/path_utilities'
|
7
6
|
require 'command-t/scanner/file_scanner'
|
8
7
|
|
@@ -12,45 +11,39 @@ module CommandT
|
|
12
11
|
class FindFileScanner < FileScanner
|
13
12
|
include VIM::PathUtilities
|
14
13
|
|
15
|
-
def paths
|
16
|
-
|
17
|
-
|
14
|
+
def paths!
|
15
|
+
# temporarily set field separator to NUL byte; this setting is
|
16
|
+
# respected by both `readlines` and `chomp!` below, and makes it easier
|
17
|
+
# to parse the output of `find -print0`
|
18
|
+
separator = $/
|
19
|
+
$/ = "\x00"
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
unless @scan_dot_directories
|
26
|
-
dot_directory_filter = [
|
27
|
-
'-not', '-path', "#{@path}/.*/*", # top-level dot dir
|
28
|
-
'-and', '-not', '-path', "#{@path}/*/.*/*" # lower-level dot dir
|
29
|
-
]
|
30
|
-
end
|
21
|
+
unless @scan_dot_directories
|
22
|
+
dot_directory_filter = [
|
23
|
+
'-not', '-path', "#{@path}/.*/*", # top-level dot dir
|
24
|
+
'-and', '-not', '-path', "#{@path}/*/.*/*" # lower-level dot dir
|
25
|
+
]
|
26
|
+
end
|
31
27
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
47
|
-
@paths[@path] = paths
|
28
|
+
paths = []
|
29
|
+
Open3.popen3(*([
|
30
|
+
'find', '-L', # follow symlinks
|
31
|
+
@path, # anchor search here
|
32
|
+
'-maxdepth', @max_depth.to_s, # limit depth of DFS
|
33
|
+
'-type', 'f', # only show regular files (not dirs etc)
|
34
|
+
dot_directory_filter, # possibly skip out dot directories
|
35
|
+
'-print0' # NUL-terminate results
|
36
|
+
].flatten.compact)) do |stdin, stdout, stderr|
|
37
|
+
counter = 1
|
38
|
+
stdout.readlines.each do |line|
|
39
|
+
next if path_excluded?(line.chomp!)
|
40
|
+
paths << line[@prefix_len..-1]
|
41
|
+
break if (counter += 1) > @max_files
|
48
42
|
end
|
49
|
-
ensure
|
50
|
-
$/ = separator
|
51
|
-
set_wild_ignore(@base_wild_ignore)
|
52
43
|
end
|
53
|
-
|
44
|
+
paths
|
45
|
+
ensure
|
46
|
+
$/ = separator
|
54
47
|
end
|
55
48
|
end # class FindFileScanner
|
56
49
|
end # class FileScanner
|