command-t 1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,24 @@
1
+ # Copyright 2010 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
+ CFLAGS += -std=c99 -Wall -Wextra -Wno-unused-parameter
@@ -0,0 +1,65 @@
1
+ // Copyright 2010 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
+ #include "match.h"
25
+ #include "matcher.h"
26
+
27
+ VALUE mCommandT = 0; // module CommandT
28
+ VALUE cCommandTMatch = 0; // class CommandT::Match
29
+ VALUE cCommandTMatcher = 0; // class CommandT::Matcher
30
+
31
+ VALUE CommandT_option_from_hash(const char *option, VALUE hash)
32
+ {
33
+ if (NIL_P(hash))
34
+ return Qnil;
35
+ VALUE key = ID2SYM(rb_intern(option));
36
+ if (rb_funcall(hash, rb_intern("has_key?"), 1, key) == Qtrue)
37
+ return rb_hash_aref(hash, key);
38
+ else
39
+ return Qnil;
40
+ }
41
+
42
+ void Init_ext()
43
+ {
44
+ // module CommandT
45
+ mCommandT = rb_define_module("CommandT");
46
+
47
+ // class CommandT::Match
48
+ cCommandTMatch = rb_define_class_under(mCommandT, "Match", rb_cObject);
49
+
50
+ // methods
51
+ rb_define_method(cCommandTMatch, "initialize", CommandTMatch_initialize, -1);
52
+ rb_define_method(cCommandTMatch, "matches?", CommandTMatch_matches, 0);
53
+ rb_define_method(cCommandTMatch, "to_s", CommandTMatch_to_s, 0);
54
+
55
+ // attributes
56
+ rb_define_attr(cCommandTMatch, "score", Qtrue, Qfalse); // reader: true, writer: false
57
+
58
+ // class CommandT::Matcher
59
+ cCommandTMatcher = rb_define_class_under(mCommandT, "Matcher", rb_cObject);
60
+
61
+ // methods
62
+ rb_define_method(cCommandTMatcher, "initialize", CommandTMatcher_initialize, -1);
63
+ rb_define_method(cCommandTMatcher, "sorted_matches_for", CommandTMatcher_sorted_matches_for, 2);
64
+ rb_define_method(cCommandTMatcher, "matches_for", CommandTMatcher_matches_for, 1);
65
+ }
@@ -0,0 +1,36 @@
1
+ // Copyright 2010 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
+ #include <ruby.h>
25
+
26
+ extern VALUE mCommandT; // module CommandT
27
+ extern VALUE cCommandTMatch; // class CommandT::Match
28
+ extern VALUE cCommandTMatcher; // class CommandT::Matcher
29
+
30
+ // Encapsulates common pattern of checking for an option in an optional
31
+ // options hash. The hash itself may be nil, but an exception will be
32
+ // raised if it is not nil and not a hash.
33
+ VALUE CommandT_option_from_hash(const char *option, VALUE hash);
34
+
35
+ // Debugging macro.
36
+ #define ruby_inspect(obj) rb_funcall(rb_mKernel, rb_intern("p"), 1, obj)
@@ -0,0 +1,32 @@
1
+ # Copyright 2010 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 'mkmf'
25
+
26
+ def missing item
27
+ puts "couldn't find #{item} (required)"
28
+ exit 1
29
+ end
30
+
31
+ have_header('ruby.h') or missing('ruby.h')
32
+ create_makefile('ext')
@@ -0,0 +1,52 @@
1
+ # Copyright 2010-2011 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/ext' # CommandT::Matcher
25
+
26
+ module CommandT
27
+ # Encapsulates a Scanner instance (which builds up a list of available files
28
+ # in a directory) and a Matcher instance (which selects from that list based
29
+ # on a search string).
30
+ #
31
+ # Specialized subclasses use different kinds of scanners adapted for
32
+ # different kinds of search (files, buffers).
33
+ class Finder
34
+ def initialize path = Dir.pwd, options = {}
35
+ raise RuntimeError, 'Subclass responsibility'
36
+ end
37
+
38
+ # Options:
39
+ # :limit (integer): limit the number of returned matches
40
+ def sorted_matches_for str, options = {}
41
+ @matcher.sorted_matches_for str, options
42
+ end
43
+
44
+ def flush
45
+ @scanner.flush
46
+ end
47
+
48
+ def path= path
49
+ @scanner.path = path
50
+ end
51
+ end # class Finder
52
+ end # CommandT
@@ -0,0 +1,35 @@
1
+ # Copyright 2010-2011 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/ext' # CommandT::Matcher
25
+ require 'command-t/scanner/buffer_scanner'
26
+ require 'command-t/finder'
27
+
28
+ module CommandT
29
+ class BufferFinder < Finder
30
+ def initialize
31
+ @scanner = BufferScanner.new
32
+ @matcher = Matcher.new @scanner, :always_show_dot_files => true
33
+ end
34
+ end # class BufferFinder
35
+ end # CommandT
@@ -0,0 +1,35 @@
1
+ # Copyright 2010-2011 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/ext' # CommandT::Matcher
25
+ require 'command-t/finder'
26
+ require 'command-t/scanner/file_scanner'
27
+
28
+ module CommandT
29
+ class FileFinder < Finder
30
+ def initialize path = Dir.pwd, options = {}
31
+ @scanner = FileScanner.new path, options
32
+ @matcher = Matcher.new @scanner, options
33
+ end
34
+ end # class FileFinder
35
+ end # CommandT
@@ -0,0 +1,189 @@
1
+ // Copyright 2010 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
+ #include "match.h"
25
+ #include "ext.h"
26
+ #include "ruby_compat.h"
27
+
28
+ // use a struct to make passing params during recursion easier
29
+ typedef struct
30
+ {
31
+ char *str_p; // pointer to string to be searched
32
+ long str_len; // length of same
33
+ char *abbrev_p; // pointer to search string (abbreviation)
34
+ long abbrev_len; // length of same
35
+ double max_score_per_char;
36
+ int dot_file; // boolean: true if str is a dot-file
37
+ int always_show_dot_files; // boolean
38
+ int never_show_dot_files; // boolean
39
+ } matchinfo_t;
40
+
41
+ double recursive_match(matchinfo_t *m, // sharable meta-data
42
+ long str_idx, // where in the path string to start
43
+ long abbrev_idx, // where in the search string to start
44
+ long last_idx, // location of last matched character
45
+ double score) // cumulative score so far
46
+ {
47
+ double seen_score = 0; // remember best score seen via recursion
48
+ int dot_file_match = 0; // true if abbrev matches a dot-file
49
+ int dot_search = 0; // true if searching for a dot
50
+
51
+ for (long i = abbrev_idx; i < m->abbrev_len; i++)
52
+ {
53
+ char c = m->abbrev_p[i];
54
+ if (c == '.')
55
+ dot_search = 1;
56
+ int found = 0;
57
+ for (long j = str_idx; j < m->str_len; j++, str_idx++)
58
+ {
59
+ char d = m->str_p[j];
60
+ if (d == '.')
61
+ {
62
+ if (j == 0 || m->str_p[j - 1] == '/')
63
+ {
64
+ m->dot_file = 1; // this is a dot-file
65
+ if (dot_search) // and we are searching for a dot
66
+ dot_file_match = 1; // so this must be a match
67
+ }
68
+ }
69
+ else if (d >= 'A' && d <= 'Z')
70
+ d += 'a' - 'A'; // add 32 to downcase
71
+ if (c == d)
72
+ {
73
+ found = 1;
74
+ dot_search = 0;
75
+
76
+ // calculate score
77
+ double score_for_char = m->max_score_per_char;
78
+ long distance = j - last_idx;
79
+ if (distance > 1)
80
+ {
81
+ double factor = 1.0;
82
+ char last = m->str_p[j - 1];
83
+ char curr = m->str_p[j]; // case matters, so get again
84
+ if (last == '/')
85
+ factor = 0.9;
86
+ else if (last == '-' ||
87
+ last == '_' ||
88
+ last == ' ' ||
89
+ (last >= '0' && last <= '9'))
90
+ factor = 0.8;
91
+ else if (last >= 'a' && last <= 'z' &&
92
+ curr >= 'A' && curr <= 'Z')
93
+ factor = 0.8;
94
+ else if (last == '.')
95
+ factor = 0.7;
96
+ else
97
+ // if no "special" chars behind char, factor diminishes
98
+ // as distance from last matched char increases
99
+ factor = (1.0 / distance) * 0.75;
100
+ score_for_char *= factor;
101
+ }
102
+
103
+ if (++j < m->str_len)
104
+ {
105
+ // bump cursor one char to the right and
106
+ // use recursion to try and find a better match
107
+ double sub_score = recursive_match(m, j, i, last_idx, score);
108
+ if (sub_score > seen_score)
109
+ seen_score = sub_score;
110
+ }
111
+
112
+ score += score_for_char;
113
+ last_idx = str_idx++;
114
+ break;
115
+ }
116
+ }
117
+ if (!found)
118
+ return 0.0;
119
+ }
120
+ if (m->dot_file)
121
+ {
122
+ if (m->never_show_dot_files ||
123
+ (!dot_file_match && !m->always_show_dot_files))
124
+ return 0.0;
125
+ }
126
+ return (score > seen_score) ? score : seen_score;
127
+ }
128
+
129
+ // Match.new abbrev, string, options = {}
130
+ VALUE CommandTMatch_initialize(int argc, VALUE *argv, VALUE self)
131
+ {
132
+ // process arguments: 2 mandatory, 1 optional
133
+ VALUE str, abbrev, options;
134
+ if (rb_scan_args(argc, argv, "21", &str, &abbrev, &options) == 2)
135
+ options = Qnil;
136
+ str = StringValue(str);
137
+ abbrev = StringValue(abbrev); // already downcased by caller
138
+
139
+ // check optional options hash for overrides
140
+ VALUE always_show_dot_files = CommandT_option_from_hash("always_show_dot_files", options);
141
+ VALUE never_show_dot_files = CommandT_option_from_hash("never_show_dot_files", options);
142
+
143
+ matchinfo_t m;
144
+ m.str_p = RSTRING_PTR(str);
145
+ m.str_len = RSTRING_LEN(str);
146
+ m.abbrev_p = RSTRING_PTR(abbrev);
147
+ m.abbrev_len = RSTRING_LEN(abbrev);
148
+ m.max_score_per_char = (1.0 / m.str_len + 1.0 / m.abbrev_len) / 2;
149
+ m.dot_file = 0;
150
+ m.always_show_dot_files = always_show_dot_files == Qtrue;
151
+ m.never_show_dot_files = never_show_dot_files == Qtrue;
152
+
153
+ // calculate score
154
+ double score = 1.0;
155
+ if (m.abbrev_len == 0) // special case for zero-length search string
156
+ {
157
+ // filter out dot files
158
+ if (!m.always_show_dot_files)
159
+ {
160
+ for (long i = 0; i < m.str_len; i++)
161
+ {
162
+ char c = m.str_p[i];
163
+ if (c == '.' && (i == 0 || m.str_p[i - 1] == '/'))
164
+ {
165
+ score = 0.0;
166
+ break;
167
+ }
168
+ }
169
+ }
170
+ }
171
+ else // normal case
172
+ score = recursive_match(&m, 0, 0, 0, 0.0);
173
+
174
+ // clean-up and final book-keeping
175
+ rb_iv_set(self, "@score", rb_float_new(score));
176
+ rb_iv_set(self, "@str", str);
177
+ return Qnil;
178
+ }
179
+
180
+ VALUE CommandTMatch_matches(VALUE self)
181
+ {
182
+ double score = NUM2DBL(rb_iv_get(self, "@score"));
183
+ return score > 0 ? Qtrue : Qfalse;
184
+ }
185
+
186
+ VALUE CommandTMatch_to_s(VALUE self)
187
+ {
188
+ return rb_iv_get(self, "@str");
189
+ }