command-t 1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+ }