ver-command_t 0.1.0

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.
data/LICENSE ADDED
@@ -0,0 +1,22 @@
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.
data/README.md ADDED
@@ -0,0 +1,12 @@
1
+ CommandT for VER
2
+ ================
3
+
4
+ Install
5
+ -------
6
+ gem install ver-command_t
7
+ cat >> $HOME/.config/ver/rc.rb
8
+ require 'ver-command_t'
9
+
10
+ Use
11
+ ---
12
+ Hit Control-t.
@@ -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_matchers_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)
Binary file
@@ -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,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
+ }
@@ -0,0 +1,29 @@
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 CommandTMatch_initialize(int argc, VALUE *argv, VALUE self);
27
+ extern VALUE CommandTMatch_matches(VALUE self);
28
+ extern VALUE CommandTMatch_score(VALUE self);
29
+ extern VALUE CommandTMatch_to_s(VALUE self);
@@ -0,0 +1,164 @@
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 <stdlib.h> /* for qsort() */
25
+ #include <string.h> /* for strcmp() */
26
+ #include "matcher.h"
27
+ #include "ext.h"
28
+ #include "ruby_compat.h"
29
+
30
+ // comparison function for use with qsort
31
+ int comp_alpha(const void *a, const void *b)
32
+ {
33
+ VALUE a_val = *(VALUE *)a;
34
+ VALUE b_val = *(VALUE *)b;
35
+ ID to_s = rb_intern("to_s");
36
+
37
+ VALUE a_str = rb_funcall(a_val, to_s, 0);
38
+ VALUE b_str = rb_funcall(b_val, to_s, 0);
39
+ char *a_p = RSTRING_PTR(a_str);
40
+ long a_len = RSTRING_LEN(a_str);
41
+ char *b_p = RSTRING_PTR(b_str);
42
+ long b_len = RSTRING_LEN(b_str);
43
+ int order = 0;
44
+ if (a_len > b_len)
45
+ {
46
+ order = strncmp(a_p, b_p, b_len);
47
+ if (order == 0)
48
+ order = 1; // shorter string (b) wins
49
+ }
50
+ else if (a_len < b_len)
51
+ {
52
+ order = strncmp(a_p, b_p, a_len);
53
+ if (order == 0)
54
+ order = -1; // shorter string (a) wins
55
+ }
56
+ else
57
+ order = strncmp(a_p, b_p, a_len);
58
+ return order;
59
+ }
60
+
61
+ // comparison function for use with qsort
62
+ int comp_score(const void *a, const void *b)
63
+ {
64
+ VALUE a_val = *(VALUE *)a;
65
+ VALUE b_val = *(VALUE *)b;
66
+ ID score = rb_intern("score");
67
+ double a_score = RFLOAT_VALUE(rb_funcall(a_val, score, 0));
68
+ double b_score = RFLOAT_VALUE(rb_funcall(b_val, score, 0));
69
+ if (a_score > b_score)
70
+ return -1; // a scores higher, a should appear sooner
71
+ else if (a_score < b_score)
72
+ return 1; // b scores higher, a should appear later
73
+ else
74
+ return comp_alpha(a, b);
75
+ }
76
+
77
+ VALUE CommandTMatcher_initialize(int argc, VALUE *argv, VALUE self)
78
+ {
79
+ // process arguments: 1 mandatory, 1 optional
80
+ VALUE scanner, options;
81
+ if (rb_scan_args(argc, argv, "11", &scanner, &options) == 1)
82
+ options = Qnil;
83
+ if (NIL_P(scanner))
84
+ rb_raise(rb_eArgError, "nil scanner");
85
+ rb_iv_set(self, "@scanner", scanner);
86
+
87
+ // check optional options hash for overrides
88
+ VALUE always_show_dot_files = CommandT_option_from_hash("always_show_dot_files", options);
89
+ if (always_show_dot_files != Qtrue)
90
+ always_show_dot_files = Qfalse;
91
+ VALUE never_show_dot_files = CommandT_option_from_hash("never_show_dot_files", options);
92
+ if (never_show_dot_files != Qtrue)
93
+ never_show_dot_files = Qfalse;
94
+ rb_iv_set(self, "@always_show_dot_files", always_show_dot_files);
95
+ rb_iv_set(self, "@never_show_dot_files", never_show_dot_files);
96
+ return Qnil;
97
+ }
98
+
99
+ VALUE CommandTMatcher_sorted_matchers_for(VALUE self, VALUE abbrev, VALUE options)
100
+ {
101
+ // process optional options hash
102
+ VALUE limit_option = CommandT_option_from_hash("limit", options);
103
+
104
+ // get unsorted matches
105
+ VALUE matches = CommandTMatcher_matches_for(self, abbrev);
106
+
107
+ abbrev = StringValue(abbrev);
108
+ if (RSTRING_LEN(abbrev) == 0 ||
109
+ (RSTRING_LEN(abbrev) == 1 && RSTRING_PTR(abbrev)[0] == '.'))
110
+ // alphabetic order if search string is only "" or "."
111
+ qsort(RARRAY_PTR(matches), RARRAY_LEN(matches), sizeof(VALUE), comp_alpha);
112
+ else
113
+ // for all other non-empty search strings, sort by score
114
+ qsort(RARRAY_PTR(matches), RARRAY_LEN(matches), sizeof(VALUE), comp_score);
115
+
116
+ // apply optional limit option
117
+ long limit = NIL_P(limit_option) ? 0 : NUM2LONG(limit_option);
118
+ if (limit == 0 || RARRAY_LEN(matches)< limit)
119
+ limit = RARRAY_LEN(matches);
120
+
121
+ // will return an array of strings, not an array of Match objects
122
+ for (long i = 0; i < limit; i++)
123
+ {
124
+ VALUE str = rb_funcall(RARRAY_PTR(matches)[i], rb_intern("to_s"), 0);
125
+ RARRAY_PTR(matches)[i] = str;
126
+ }
127
+
128
+ // trim off any items beyond the limit
129
+ if (limit < RARRAY_LEN(matches))
130
+ (void)rb_funcall(matches, rb_intern("slice!"), 2, LONG2NUM(limit),
131
+ LONG2NUM(RARRAY_LEN(matches) - limit));
132
+ return matches;
133
+ }
134
+
135
+ VALUE CommandTMatcher_matches_for(VALUE self, VALUE abbrev)
136
+ {
137
+ if (NIL_P(abbrev))
138
+ rb_raise(rb_eArgError, "nil abbrev");
139
+ VALUE matches = rb_ary_new();
140
+ VALUE scanner = rb_iv_get(self, "@scanner");
141
+ VALUE always_show_dot_files = rb_iv_get(self, "@always_show_dot_files");
142
+ VALUE never_show_dot_files = rb_iv_get(self, "@never_show_dot_files");
143
+ VALUE options = Qnil;
144
+ if (always_show_dot_files == Qtrue)
145
+ {
146
+ options = rb_hash_new();
147
+ rb_hash_aset(options, ID2SYM(rb_intern("always_show_dot_files")), always_show_dot_files);
148
+ }
149
+ else if (never_show_dot_files == Qtrue)
150
+ {
151
+ options = rb_hash_new();
152
+ rb_hash_aset(options, ID2SYM(rb_intern("never_show_dot_files")), never_show_dot_files);
153
+ }
154
+ abbrev = rb_funcall(abbrev, rb_intern("downcase"), 0);
155
+ VALUE paths = rb_funcall(scanner, rb_intern("paths"), 0);
156
+ for (long i = 0, max = RARRAY_LEN(paths); i < max; i++)
157
+ {
158
+ VALUE path = RARRAY_PTR(paths)[i];
159
+ VALUE match = rb_funcall(cCommandTMatch, rb_intern("new"), 3, path, abbrev, options);
160
+ if (rb_funcall(match, rb_intern("matches?"), 0) == Qtrue)
161
+ rb_funcall(matches, rb_intern("push"), 1, match);
162
+ }
163
+ return matches;
164
+ }
@@ -0,0 +1,30 @@
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 CommandTMatcher_initialize(int argc, VALUE *argv, VALUE self);
27
+ extern VALUE CommandTMatcher_sorted_matchers_for(VALUE self, VALUE abbrev, VALUE options);
28
+
29
+ // most likely the function will be subsumed by the sorted_matcher_for function
30
+ extern VALUE CommandTMatcher_matches_for(VALUE self, VALUE abbrev);
@@ -0,0 +1,20 @@
1
+ have_header: checking for ruby.h... -------------------- yes
2
+
3
+ "gcc -o conftest -I/home/tass/.rvm/rubies/ruby-1.9.2-p0/include/ruby-1.9.1/x86_64-linux -I/home/tass/.rvm/rubies/ruby-1.9.2-p0/include/ruby-1.9.1/ruby/backward -I/home/tass/.rvm/rubies/ruby-1.9.2-p0/include/ruby-1.9.1 -I. -O2 -g -Wall -fPIC conftest.c -L. -L/home/tass/.rvm/rubies/ruby-1.9.2-p0/lib -Wl,-R/home/tass/.rvm/rubies/ruby-1.9.2-p0/lib -L. -rdynamic -Wl,-export-dynamic -Wl,-R -Wl,/home/tass/.rvm/rubies/ruby-1.9.2-p0/lib -L/home/tass/.rvm/rubies/ruby-1.9.2-p0/lib -lruby-static -lpthread -lrt -ldl -lcrypt -lm -lc"
4
+ checked program was:
5
+ /* begin */
6
+ 1: #include "ruby.h"
7
+ 2:
8
+ 3: int main() {return 0;}
9
+ /* end */
10
+
11
+ "gcc -E -I/home/tass/.rvm/rubies/ruby-1.9.2-p0/include/ruby-1.9.1/x86_64-linux -I/home/tass/.rvm/rubies/ruby-1.9.2-p0/include/ruby-1.9.1/ruby/backward -I/home/tass/.rvm/rubies/ruby-1.9.2-p0/include/ruby-1.9.1 -I. -O2 -g -Wall -fPIC conftest.c -o conftest.i"
12
+ checked program was:
13
+ /* begin */
14
+ 1: #include "ruby.h"
15
+ 2:
16
+ 3: #include <ruby.h>
17
+ /* end */
18
+
19
+ --------------------
20
+