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.
@@ -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 = Constant.find_all_by_name(name, :include => "entries")
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 = Constant.find_all_by_name("#{name}::ClassMethods", :include => "entries") if constants.empty?
36
+ constants = scope.find_all_by_name("#{name}::ClassMethods", :include => "entries") if constants.empty?
34
37
  # Find by name beginning with <blah>.
35
- constants = Constant.all(:conditions => ["name LIKE ?", name + "%"], :include => "entries") if constants.empty?
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 = Constant.find_by_sql("select * from constants where name LIKE '#{match}'") if constants.empty?
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 = Entry.find_all_by_name(name.to_s)
86
+ methods = scope.find_all_by_name(name.to_s)
83
87
  # Start match
84
- methods = Entry.all(:conditions => ["name LIKE ?", name.to_s + "%"]) if methods.empty?
88
+ methods = scope.all(:conditions => ["entries.name LIKE ?", name.to_s + "%"]) if methods.empty?
85
89
  # Wildcard substitution
86
- methods = Entry.find_by_sql("select * from entries where name LIKE '#{name.to_s.gsub("*", "%")}'") if methods.empty?
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 = Entry.find_by_sql("select * from entries where name LIKE '%#{name.to_s.split("").join("%")}%'") if methods.empty?
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 /^Rails/i.match(msg)
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
- output = output.select { |m| m.api.name == options[:api] } if options[:api]
133
- return output
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("<", "&lt;").gsub("&gt;", ">")}" })
33
+ doc = Nokogiri::HTML(doc.gsub(/<a(.*?)>(.*?)<\/a>/m) { "<a#{$1}>#{$2.gsub("<", "&lt;").gsub(">", "&gt;")}" })
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.find_or_create_by_hash(:name => constant, :url => url)
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.find_or_create_by_hash(:name => method, :url => url)
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