lookup 0.4.1 → 1.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +17 -20
- data/Rakefile +1 -0
- data/doc/classes/APILookup/Api.src/M000010.html +40 -0
- data/doc/classes/APILookup/Api.src/M000011.html +21 -0
- data/doc/classes/APILookup.src/M000003.html +24 -0
- data/doc/classes/APILookup.src/M000004.html +22 -0
- data/doc/classes/APILookup.src/M000005.html +33 -0
- data/doc/classes/APILookup.src/M000006.html +21 -0
- data/doc/classes/APILookup.src/M000007.html +33 -0
- data/doc/classes/APILookup.src/M000008.html +35 -0
- data/doc/classes/APILookup.src/M000009.html +52 -0
- data/doc/classes/SetupTables.src/M000001.html +18 -0
- data/doc/classes/SetupTables.src/M000002.html +34 -0
- data/doc/files/lib/lookup_rb.html +112 -0
- data/doc/files/lib/lookup_sqlite3.html +0 -0
- data/doc/rdoc-style.css +208 -0
- data/lib/lookup.rb +31 -24
- data/lib/models.rb +5 -3
- data/spec/apis/{rails → rails-2.3.8}/classes.html +0 -0
- data/spec/apis/{rails → rails-2.3.8}/methods.html +0 -0
- data/spec/apis/rails-3.0.0/classes.html +850 -0
- data/spec/apis/rails-3.0.0/methods.html +10185 -0
- data/spec/lookup_spec.rb +23 -12
- data/spec/regressions_spec.rb +1 -1
- data/spec/spec_helper.rb +10 -8
- metadata +59 -14
- data/lib/config.rb +0 -5
data/doc/rdoc-style.css
ADDED
@@ -0,0 +1,208 @@
|
|
1
|
+
|
2
|
+
body {
|
3
|
+
font-family: Verdana,Arial,Helvetica,sans-serif;
|
4
|
+
font-size: 90%;
|
5
|
+
margin: 0;
|
6
|
+
margin-left: 40px;
|
7
|
+
padding: 0;
|
8
|
+
background: white;
|
9
|
+
}
|
10
|
+
|
11
|
+
h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
|
12
|
+
h1 { font-size: 150%; }
|
13
|
+
h2,h3,h4 { margin-top: 1em; }
|
14
|
+
|
15
|
+
a { background: #eef; color: #039; text-decoration: none; }
|
16
|
+
a:hover { background: #039; color: #eef; }
|
17
|
+
|
18
|
+
/* Override the base stylesheet's Anchor inside a table cell */
|
19
|
+
td > a {
|
20
|
+
background: transparent;
|
21
|
+
color: #039;
|
22
|
+
text-decoration: none;
|
23
|
+
}
|
24
|
+
|
25
|
+
/* and inside a section title */
|
26
|
+
.section-title > a {
|
27
|
+
background: transparent;
|
28
|
+
color: #eee;
|
29
|
+
text-decoration: none;
|
30
|
+
}
|
31
|
+
|
32
|
+
/* === Structural elements =================================== */
|
33
|
+
|
34
|
+
div#index {
|
35
|
+
margin: 0;
|
36
|
+
margin-left: -40px;
|
37
|
+
padding: 0;
|
38
|
+
font-size: 90%;
|
39
|
+
}
|
40
|
+
|
41
|
+
|
42
|
+
div#index a {
|
43
|
+
margin-left: 0.7em;
|
44
|
+
}
|
45
|
+
|
46
|
+
div#index .section-bar {
|
47
|
+
margin-left: 0px;
|
48
|
+
padding-left: 0.7em;
|
49
|
+
background: #ccc;
|
50
|
+
font-size: small;
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
div#classHeader, div#fileHeader {
|
55
|
+
width: auto;
|
56
|
+
color: white;
|
57
|
+
padding: 0.5em 1.5em 0.5em 1.5em;
|
58
|
+
margin: 0;
|
59
|
+
margin-left: -40px;
|
60
|
+
border-bottom: 3px solid #006;
|
61
|
+
}
|
62
|
+
|
63
|
+
div#classHeader a, div#fileHeader a {
|
64
|
+
background: inherit;
|
65
|
+
color: white;
|
66
|
+
}
|
67
|
+
|
68
|
+
div#classHeader td, div#fileHeader td {
|
69
|
+
background: inherit;
|
70
|
+
color: white;
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
div#fileHeader {
|
75
|
+
background: #057;
|
76
|
+
}
|
77
|
+
|
78
|
+
div#classHeader {
|
79
|
+
background: #048;
|
80
|
+
}
|
81
|
+
|
82
|
+
|
83
|
+
.class-name-in-header {
|
84
|
+
font-size: 180%;
|
85
|
+
font-weight: bold;
|
86
|
+
}
|
87
|
+
|
88
|
+
|
89
|
+
div#bodyContent {
|
90
|
+
padding: 0 1.5em 0 1.5em;
|
91
|
+
}
|
92
|
+
|
93
|
+
div#description {
|
94
|
+
padding: 0.5em 1.5em;
|
95
|
+
background: #efefef;
|
96
|
+
border: 1px dotted #999;
|
97
|
+
}
|
98
|
+
|
99
|
+
div#description h1,h2,h3,h4,h5,h6 {
|
100
|
+
color: #125;;
|
101
|
+
background: transparent;
|
102
|
+
}
|
103
|
+
|
104
|
+
div#validator-badges {
|
105
|
+
text-align: center;
|
106
|
+
}
|
107
|
+
div#validator-badges img { border: 0; }
|
108
|
+
|
109
|
+
div#copyright {
|
110
|
+
color: #333;
|
111
|
+
background: #efefef;
|
112
|
+
font: 0.75em sans-serif;
|
113
|
+
margin-top: 5em;
|
114
|
+
margin-bottom: 0;
|
115
|
+
padding: 0.5em 2em;
|
116
|
+
}
|
117
|
+
|
118
|
+
|
119
|
+
/* === Classes =================================== */
|
120
|
+
|
121
|
+
table.header-table {
|
122
|
+
color: white;
|
123
|
+
font-size: small;
|
124
|
+
}
|
125
|
+
|
126
|
+
.type-note {
|
127
|
+
font-size: small;
|
128
|
+
color: #DEDEDE;
|
129
|
+
}
|
130
|
+
|
131
|
+
.xxsection-bar {
|
132
|
+
background: #eee;
|
133
|
+
color: #333;
|
134
|
+
padding: 3px;
|
135
|
+
}
|
136
|
+
|
137
|
+
.section-bar {
|
138
|
+
color: #333;
|
139
|
+
border-bottom: 1px solid #999;
|
140
|
+
margin-left: -20px;
|
141
|
+
}
|
142
|
+
|
143
|
+
|
144
|
+
.section-title {
|
145
|
+
background: #79a;
|
146
|
+
color: #eee;
|
147
|
+
padding: 3px;
|
148
|
+
margin-top: 2em;
|
149
|
+
margin-left: -30px;
|
150
|
+
border: 1px solid #999;
|
151
|
+
}
|
152
|
+
|
153
|
+
.top-aligned-row { vertical-align: top }
|
154
|
+
.bottom-aligned-row { vertical-align: bottom }
|
155
|
+
|
156
|
+
/* --- Context section classes ----------------------- */
|
157
|
+
|
158
|
+
.context-row { }
|
159
|
+
.context-item-name { font-family: monospace; font-weight: bold; color: black; }
|
160
|
+
.context-item-value { font-size: small; color: #448; }
|
161
|
+
.context-item-desc { color: #333; padding-left: 2em; }
|
162
|
+
|
163
|
+
/* --- Method classes -------------------------- */
|
164
|
+
.method-detail {
|
165
|
+
background: #efefef;
|
166
|
+
padding: 0;
|
167
|
+
margin-top: 0.5em;
|
168
|
+
margin-bottom: 1em;
|
169
|
+
border: 1px dotted #ccc;
|
170
|
+
}
|
171
|
+
.method-heading {
|
172
|
+
color: black;
|
173
|
+
background: #ccc;
|
174
|
+
border-bottom: 1px solid #666;
|
175
|
+
padding: 0.2em 0.5em 0 0.5em;
|
176
|
+
}
|
177
|
+
.method-signature { color: black; background: inherit; }
|
178
|
+
.method-name { font-weight: bold; }
|
179
|
+
.method-args { font-style: italic; }
|
180
|
+
.method-description { padding: 0 0.5em 0 0.5em; }
|
181
|
+
|
182
|
+
/* --- Source code sections -------------------- */
|
183
|
+
|
184
|
+
a.source-toggle { font-size: 90%; }
|
185
|
+
div.method-source-code {
|
186
|
+
background: #262626;
|
187
|
+
color: #ffdead;
|
188
|
+
margin: 1em;
|
189
|
+
padding: 0.5em;
|
190
|
+
border: 1px dashed #999;
|
191
|
+
overflow: hidden;
|
192
|
+
}
|
193
|
+
|
194
|
+
div.method-source-code pre { color: #ffdead; overflow: hidden; }
|
195
|
+
|
196
|
+
/* --- Ruby keyword styles --------------------- */
|
197
|
+
|
198
|
+
.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
|
199
|
+
|
200
|
+
.ruby-constant { color: #7fffd4; background: transparent; }
|
201
|
+
.ruby-keyword { color: #00ffff; background: transparent; }
|
202
|
+
.ruby-ivar { color: #eedd82; background: transparent; }
|
203
|
+
.ruby-operator { color: #00ffee; background: transparent; }
|
204
|
+
.ruby-identifier { color: #ffdead; background: transparent; }
|
205
|
+
.ruby-node { color: #ffa07a; background: transparent; }
|
206
|
+
.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
|
207
|
+
.ruby-regexp { color: #ffa07a; background: transparent; }
|
208
|
+
.ruby-value { color: #7fffd4; background: transparent; }
|
data/lib/lookup.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'bundler'
|
2
3
|
require 'net/http'
|
3
4
|
|
5
|
+
Bundler.setup
|
6
|
+
Bundler.require(:default)
|
4
7
|
require 'active_record'
|
5
|
-
require 'nokogiri'
|
6
|
-
require 'find_by_hash'
|
7
8
|
|
8
9
|
module APILookup
|
9
10
|
|
@@ -12,7 +13,8 @@ module APILookup
|
|
12
13
|
puts "Updating API, this may take a minute or two. Please be patient!"
|
13
14
|
[Constant, Entry, Api].map { |klass| klass.delete_all }
|
14
15
|
|
15
|
-
update_api!("Rails", "http://api.rubyonrails.org")
|
16
|
+
update_api!("Rails v3.0.0", "http://api.rubyonrails.org")
|
17
|
+
update_api!("Rails v2.3.8", "http://api.rubyonrails.org/v2.3.8")
|
16
18
|
update_api!("Ruby 1.8.7", "http://www.ruby-doc.org/core")
|
17
19
|
update_api!("Ruby 1.9", "http://ruby-doc.org/ruby-1.9")
|
18
20
|
|
@@ -26,16 +28,17 @@ module APILookup
|
|
26
28
|
puts "DONE (with #{name})!"
|
27
29
|
end
|
28
30
|
|
29
|
-
def find_constant(name, entry=nil)
|
31
|
+
def find_constant(name, entry=nil, options={})
|
32
|
+
scope = options[:api].constants || Constant
|
30
33
|
# Find by specific name.
|
31
|
-
constants =
|
34
|
+
constants = scope.find_all_by_name(name, :include => "entries")
|
32
35
|
# search for class methods, which is prolly what we want if we can find it
|
33
|
-
constants =
|
36
|
+
constants = scope.find_all_by_name("#{name}::ClassMethods", :include => "entries") if constants.empty?
|
34
37
|
# Find by name beginning with <blah>.
|
35
|
-
constants =
|
38
|
+
constants = scope.all(:conditions => ["constants.name LIKE ?", name + "%"], :include => "entries") if constants.empty?
|
36
39
|
# Find by fuzzy.
|
37
40
|
match="%#{name.split("").join("%")}%"
|
38
|
-
constants =
|
41
|
+
constants = scope.find_by_sql("select * from constants where name LIKE '#{match}'") if constants.empty?
|
39
42
|
regex=build_regex_from_constant(name)
|
40
43
|
constants = constants.select { |x| x.name =~ regex }
|
41
44
|
# Narrow it down to the constants that only contain the entry we are looking for.
|
@@ -76,22 +79,23 @@ module APILookup
|
|
76
79
|
|
77
80
|
# Find an entry.
|
78
81
|
# If the constant argument is passed, look it up within the scope of the constant.
|
79
|
-
def find_method(name, constant=nil)
|
82
|
+
def find_method(name, constant=nil, options = {})
|
83
|
+
scope = options[:api].entries || Entry
|
80
84
|
methods = []
|
81
85
|
# Full match
|
82
|
-
methods =
|
86
|
+
methods = scope.find_all_by_name(name.to_s)
|
83
87
|
# Start match
|
84
|
-
methods =
|
88
|
+
methods = scope.all(:conditions => ["entries.name LIKE ?", name.to_s + "%"]) if methods.empty?
|
85
89
|
# Wildcard substitution
|
86
|
-
methods =
|
90
|
+
methods = scope.find_by_sql("select * from entries where name LIKE '#{name.to_s.gsub("*", "%")}'") if methods.empty?
|
87
91
|
# Fuzzy match
|
88
|
-
methods =
|
92
|
+
methods = scope.find_by_sql("select * from entries where name LIKE '%#{name.to_s.split("").join("%")}%'") if methods.empty?
|
89
93
|
|
90
94
|
# Weight the results, last result is the first one we want shown first
|
91
95
|
methods = methods.sort_by(&:weighting)
|
92
96
|
|
93
97
|
if constant
|
94
|
-
constants = find_constant(constant)
|
98
|
+
constants = find_constant(constant, nil, options)
|
95
99
|
methods = methods.select { |m| constants.include?(m.constant) }
|
96
100
|
end
|
97
101
|
methods
|
@@ -101,36 +105,39 @@ module APILookup
|
|
101
105
|
options[:api] ||= if /^1\.9/.match(msg)
|
102
106
|
"Ruby 1.9"
|
103
107
|
elsif /^1\.8/.match(msg)
|
104
|
-
"Ruby 1.8"
|
105
|
-
elsif /^
|
106
|
-
"Rails"
|
108
|
+
"Ruby 1.8.7"
|
109
|
+
elsif /^v([\d\.]{5})/i.match(msg)
|
110
|
+
"Rails v#{$1}"
|
107
111
|
end
|
108
112
|
|
113
|
+
options[:api] = Api.find_by_name!(options[:api]) unless options[:api].is_a?(Api)
|
114
|
+
|
109
115
|
msg = msg.gsub(/^(.*?)\s/, "") if options[:api]
|
110
116
|
|
111
117
|
splitter = options[:splitter] || "#"
|
112
118
|
parts = msg.split(" ")[0..-1].flatten.map { |a| a.split(splitter) }.flatten!
|
113
119
|
# It's a constant! Oh... and there's nothing else in the string!
|
114
120
|
first = smart_rails_constant_substitutions(parts.first)
|
121
|
+
|
115
122
|
output = if /^[A-Z]/.match(first) && parts.size == 1
|
116
|
-
find_constant(first)
|
123
|
+
find_constant(first, nil, options)
|
117
124
|
# It's a method!
|
118
125
|
else
|
119
126
|
# Right, so they only specified one argument. Therefore, we look everywhere.
|
120
127
|
if parts.size == 1
|
121
|
-
o = find_method(parts.last)
|
128
|
+
o = find_method(parts.last, nil, options)
|
122
129
|
# Left, so they specified two arguments. First is probably a constant, so let's find that!
|
123
130
|
else
|
124
|
-
o = find_method(parts.last, first)
|
131
|
+
o = find_method(parts.last, first, options)
|
125
132
|
end
|
126
133
|
o
|
127
134
|
end
|
128
135
|
|
129
|
-
|
130
136
|
output = search(msg, options.merge(:splitter => ".")) if output.empty? && splitter != "."
|
131
|
-
|
132
|
-
|
133
|
-
|
137
|
+
selected_output = output.select { |m| options[:api].name == m.api.name }
|
138
|
+
selected_output = output if selected_output.empty?
|
139
|
+
|
140
|
+
return selected_output
|
134
141
|
end
|
135
142
|
|
136
143
|
end
|
data/lib/models.rb
CHANGED
@@ -21,6 +21,7 @@ module APILookup
|
|
21
21
|
class Api < LookupBase
|
22
22
|
set_table_name "apis"
|
23
23
|
has_many :constants, :class_name => "APILookup::Constant"
|
24
|
+
has_many :entries, :through => :constants
|
24
25
|
|
25
26
|
def update_methods!
|
26
27
|
entries = []
|
@@ -29,7 +30,8 @@ module APILookup
|
|
29
30
|
|
30
31
|
# Actual HTML on Ruby doc site is invalid.
|
31
32
|
# This makes it valid.
|
32
|
-
doc = Nokogiri::HTML(doc.gsub(/<a(.*?)>(.*?)<\/a>/) { "<a#{$1}>#{$2.gsub("<", "<").gsub("
|
33
|
+
doc = Nokogiri::HTML(doc.gsub(/<a(.*?)>(.*?)<\/a>/m) { "<a#{$1}>#{$2.gsub("<", "<").gsub(">", ">")}" })
|
34
|
+
|
33
35
|
doc.css("a").each do |a|
|
34
36
|
names = a.text.split(" ")
|
35
37
|
next if names.empty?
|
@@ -37,10 +39,10 @@ module APILookup
|
|
37
39
|
constant = names[1].gsub(/[\(|\)]/, "")
|
38
40
|
# The same constant can be defined twice in different APIs, be wary!
|
39
41
|
url = self.url + "/classes/" + constant.gsub("::", "/") + ".html"
|
40
|
-
constant = self.constants.
|
42
|
+
constant = self.constants.find_or_create_by_name_and_url(constant, url)
|
41
43
|
|
42
44
|
url = self.url + "/" + a["href"]
|
43
|
-
constant.entries.
|
45
|
+
constant.entries.find_or_create_by_name_and_url(method, url)
|
44
46
|
end
|
45
47
|
|
46
48
|
# entries.each_slice(100) do |methods|
|
File without changes
|
File without changes
|