lookup 0.4.1 → 1.0.0.beta1
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/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
|