tomdoc 0.2.3 → 0.2.4

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/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ require File.dirname(__FILE__) + '/lib/tomdoc/version'
2
+
1
3
  require 'rake/testtask'
2
4
 
3
5
  def command?(command)
@@ -33,18 +35,18 @@ end
33
35
  task :default => :test
34
36
 
35
37
  if command? :turn
36
- desc "Run tests"
37
- task :test do
38
+ desc "Run tests with turn"
39
+ task :turn do
38
40
  suffix = "-n #{ENV['TEST']}" if ENV['TEST']
39
41
  sh "turn -Ilib:. test/*.rb #{suffix}"
40
42
  end
41
- else
42
- Rake::TestTask.new do |t|
43
- t.libs << 'lib'
44
- t.libs << '.'
45
- t.pattern = 'test/**/*_test.rb'
46
- t.verbose = false
47
- end
43
+ end
44
+
45
+ Rake::TestTask.new do |t|
46
+ t.libs << 'lib'
47
+ t.libs << '.'
48
+ t.pattern = 'test/**/*_test.rb'
49
+ t.verbose = false
48
50
  end
49
51
 
50
52
 
@@ -62,20 +64,25 @@ end
62
64
  # Gems
63
65
  #
64
66
 
65
- begin
66
- require 'tomdoc/version'
67
- require 'mg'
68
- MG.new("tomdoc.gemspec")
67
+ desc "Build gem."
68
+ task :gem do
69
+ sh "gem build tomdoc.gemspec"
70
+ end
71
+
72
+ task :push => [:gem] do
73
+ file = Dir["*-#{TomDoc::VERSION}.gem"].first
74
+ sh "gem push #{file}"
75
+ end
69
76
 
70
- desc "Push a new version to Gemcutter and publish docs."
71
- task :publish => "gem:publish" do
72
- require File.dirname(__FILE__) + '/lib/tomdoc/version'
77
+ desc "tag version"
78
+ task :tag do
79
+ sh "git tag v#{TomDoc::VERSION}"
80
+ sh "git push origin master --tags"
81
+ sh "git clean -fd"
82
+ end
73
83
 
74
- sh "git tag v#{TomDoc::VERSION}"
75
- sh "git push origin master --tags"
76
- sh "git clean -fd"
77
- end
78
- rescue LoadError
79
- warn "mg not available."
80
- warn "Install it with: gem i mg"
84
+ desc "tag version and push gem to server"
85
+ task :release => [:push, :tag] do
86
+ puts "And away she goes!"
81
87
  end
88
+
@@ -31,62 +31,283 @@ module TomDoc
31
31
  end
32
32
  end
33
33
 
34
+ #
35
+ # TODO: Instead of having TomDoc::TomDoc, lets consider renaming this
36
+ # class TomDoc::Comment or something.
37
+ #
34
38
  class TomDoc
35
39
  attr_accessor :raw
36
40
 
37
- def initialize(text)
41
+ # Public: Initialize a TomDoc object.
42
+ #
43
+ # text - The raw text of a method or class/module comment.
44
+ #
45
+ # Returns new TomDoc instance.
46
+ def initialize(text, options={})
38
47
  @raw = text.to_s.strip
48
+
49
+ @arguments = []
50
+ @examples = []
51
+ @returns = []
52
+ @raises = []
53
+ @signatures = []
54
+ @signature_fields = []
55
+
56
+ parse unless @raw.empty?
39
57
  end
40
58
 
41
59
  def to_s
42
60
  @raw
43
61
  end
44
62
 
63
+ # Validate given comment text.
64
+ #
65
+ # Returns true if comment is valid, otherwise false.
45
66
  def self.valid?(text)
46
67
  new(text).valid?
47
68
  end
48
69
 
70
+ # Validate raw comment.
71
+ #
72
+ # Returns true if comment is valid, otherwise false.
49
73
  def valid?
50
- validate
51
- rescue InvalidTomDoc
52
- false
74
+ return false if !raw.include?('Returns')
75
+ return false if sections.size < 2
76
+ true
53
77
  end
54
78
 
79
+ # Validate raw comment.
80
+ #
81
+ # Returns true if comment is valid.
82
+ # Raises InvalidTomDoc if comment is not valid.
55
83
  def validate
56
84
  if !raw.include?('Returns')
57
85
  raise InvalidTomDoc.new("No `Returns' statement.")
58
86
  end
59
87
 
60
- if tomdoc.split("\n\n").size < 2
88
+ if sections.size < 2
61
89
  raise InvalidTomDoc.new("No description section found.")
62
90
  end
63
91
 
64
92
  true
65
93
  end
66
94
 
95
+ # The raw comment text cleaned-up and ready for section parsing.
96
+ #
97
+ # Returns cleaned-up comment String.
67
98
  def tomdoc
68
- #raw
69
- clean = raw.split("\n").map do |line|
70
- line =~ /^(\s*# ?)/ ? line.sub($1, '') : nil
71
- end.compact.join("\n")
72
- clean
99
+ lines = raw.split("\n")
100
+
101
+ # remove remark symbol
102
+ if lines.all?{ |line| /^\s*#/ =~ line }
103
+ lines = lines.map do |line|
104
+ line =~ /^(\s*#)/ ? line.sub($1, '') : nil
105
+ end
106
+ end
107
+
108
+ # for some reason the first line is coming in without indention
109
+ # regardless.
110
+ first = lines.shift
111
+
112
+ # remove indention
113
+ spaces = lines.map do |line|
114
+ next if line.strip.empty?
115
+ md = /^(\s*)/.match(line)
116
+ md ? md[1].size : nil
117
+ end.compact
118
+
119
+ space = spaces.min
120
+ lines = lines.map do |line|
121
+ if line.empty?
122
+ line.strip
123
+ else
124
+ line[space..-1]
125
+ end
126
+ end
127
+
128
+ # put first line back
129
+ lines.unshift(first.sub(/^\s*/,''))
130
+
131
+ lines.compact.join("\n")
73
132
  end
74
133
 
134
+ # List of comment sections. These are divided simply on "\n\n".
135
+ #
136
+ # Returns Array of comment sections.
75
137
  def sections
76
- tomdoc.split("\n\n")
138
+ parsed {
139
+ @sections
140
+ }
77
141
  end
78
142
 
143
+ # Description of method or class/module.
144
+ #
145
+ # Returns description String.
79
146
  def description
80
- sections.first
147
+ parsed {
148
+ @description
149
+ }
150
+ end
151
+
152
+ # Description of method or class/module.
153
+ #
154
+ # Returns description String.
155
+ def arguments
156
+ parsed {
157
+ @arguments
158
+ }
159
+ end
160
+ alias args arguments
161
+
162
+ # List of use examples of a method or class/module.
163
+ #
164
+ # Returns String of examples.
165
+ def examples
166
+ parsed {
167
+ @examples
168
+ }
169
+ end
170
+
171
+ # Description of a methods yield procedure.
172
+ #
173
+ # Returns String decription of yield procedure.
174
+ def yields
175
+ parsed {
176
+ @yields
177
+ }
178
+ end
179
+
180
+ # The list of retrun values a method can return.
181
+ #
182
+ # Returns Array of method return descriptions.
183
+ def returns
184
+ parsed {
185
+ @returns
186
+ }
187
+ end
188
+
189
+ # A list of errors a method might raise.
190
+ #
191
+ # Returns Array of method raises descriptions.
192
+ def raises
193
+ parsed {
194
+ @raises
195
+ }
196
+ end
197
+
198
+ # A list of alternate method signatures.
199
+ #
200
+ # Returns Array of signatures.
201
+ def signatures
202
+ parsed {
203
+ @signatures
204
+ }
205
+ end
206
+
207
+ # A list of signature fields.
208
+ #
209
+ # Returns Array of field definitions.
210
+ def signature_fields
211
+ parsed {
212
+ @signature_fields
213
+ }
214
+ end
215
+
216
+ # Check if method is public.
217
+ #
218
+ # Returns true if method is public.
219
+ def public?
220
+ parsed {
221
+ @status == 'Public'
222
+ }
223
+ end
224
+
225
+ # Check if method is internal.
226
+ #
227
+ # Returns true if method is internal.
228
+ def internal?
229
+ parsed {
230
+ @status == 'Internal'
231
+ }
232
+ end
233
+
234
+ # Check if method is deprecated.
235
+ #
236
+ # Returns true if method is deprecated.
237
+ def deprecated?
238
+ parsed {
239
+ @status == 'Deprecated'
240
+ }
241
+ end
242
+
243
+ private
244
+
245
+ # Has the comment been parsed yet?
246
+ def parsed(&block)
247
+ parse unless @parsed
248
+ block.call
249
+ end
250
+
251
+ # Internal: Parse the Tomdoc formatted comment.
252
+ #
253
+ # Returns true if there was a comment to parse.
254
+ def parse
255
+ @parsed = true
256
+
257
+ @sections = tomdoc.split("\n\n")
258
+ sections = @sections.dup
259
+
260
+ return false if sections.empty?
261
+
262
+ parse_description(sections.shift)
263
+
264
+ if sections.first && sections.first =~ /^\w+\s+\-/m
265
+ parse_arguments(sections.shift)
266
+ end
267
+
268
+ current = sections.shift
269
+ while current
270
+ case current
271
+ when /^Examples/
272
+ parse_examples(current, sections)
273
+ when /^Yields/
274
+ parse_yields(current)
275
+ when /^(Returns|Raises)/
276
+ parse_returns(current)
277
+ when /^Signature/
278
+ parse_signature(current, sections)
279
+ end
280
+ current = sections.shift
281
+ end
282
+
283
+ return @parsed
81
284
  end
82
285
 
83
- def args
286
+ # Parse description.
287
+ #
288
+ # section - String containig description.
289
+ #
290
+ # Returns nothing.
291
+ def parse_description(section)
292
+ if md = /^([A-Z]\w+\:)/.match(section)
293
+ @status = md[1].chomp(':')
294
+ @description = md.post_match.strip
295
+ else
296
+ @description = section.strip
297
+ end
298
+ end
299
+
300
+ # Parse arguments section. Arguments occur subsequent to
301
+ # the description.
302
+ #
303
+ # section - String contaning agument definitions.
304
+ #
305
+ # Returns nothing.
306
+ def parse_arguments(section)
84
307
  args = []
85
308
  last_indent = nil
86
309
 
87
- return args unless sections[1]
88
-
89
- sections[1].split("\n").each do |line|
310
+ section.split("\n").each do |line|
90
311
  next if line.strip.empty?
91
312
  indent = line.scan(/^\s*/)[0].to_s.size
92
313
 
@@ -100,54 +321,117 @@ module TomDoc
100
321
  last_indent = indent
101
322
  end
102
323
 
103
- args
324
+ @arguments = args
104
325
  end
105
326
 
106
- def examples
107
- if tomdoc =~ /(\s*Examples\s*(.+?)\s*(?:Returns|Raises))/m
108
- $2.split("\n\n")
109
- else
110
- []
327
+ # Parse examples.
328
+ #
329
+ # section - String starting with `Examples`.
330
+ # sections - All sections subsequent to section.
331
+ #
332
+ # Returns nothing.
333
+ def parse_examples(section, sections)
334
+ examples = []
335
+
336
+ section = section.sub('Examples', '').strip
337
+
338
+ examples << section unless section.empty?
339
+ while sections.first && sections.first !~ /^\S/
340
+ examples << sections.shift.strip
111
341
  end
342
+
343
+ @examples = examples
112
344
  end
113
345
 
114
- def returns
115
- if tomdoc =~ /^\s*(Returns.+)/m
116
- lines = $1.split("\n")
117
- statements = []
118
-
119
- lines.each do |line|
120
- next if line =~ /^\s*Raises/
121
- if line =~ /^\s+/
122
- statements.last << line.squeeze(' ')
123
- else
124
- statements << line
125
- end
346
+ # Parse yields section.
347
+ #
348
+ # section - String contaning Yields line.
349
+ #
350
+ # Returns nothing.
351
+ def parse_yields(section)
352
+ @yields = section.strip
353
+ end
354
+
355
+ # Parse returns section.
356
+ #
357
+ # section - String contaning Returns and/or Raises lines.
358
+ #
359
+ # Returns nothing.
360
+ def parse_returns(section)
361
+ returns, raises, current = [], [], []
362
+
363
+ lines = section.split("\n")
364
+ lines.each do |line|
365
+ case line
366
+ when /^Returns/
367
+ returns << line
368
+ current = returns
369
+ when /^Raises/
370
+ raises << line
371
+ current = raises
372
+ when /^\s+/
373
+ current.last << line.squeeze(' ')
374
+ else
375
+ current << line # TODO: What to do with non-compliant line?
126
376
  end
377
+ end
127
378
 
128
- statements
129
- else
130
- []
379
+ @returns, @raises = returns, raises
380
+ end
381
+
382
+ # Parse signature section.
383
+ #
384
+ # section - String starting with `Signature`.
385
+ # sections - All sections subsequent to section.
386
+ #
387
+ # Returns nothing.
388
+ def parse_signature(section, sections=[])
389
+ signatures = []
390
+
391
+ section = section.sub('Signature', '').strip
392
+
393
+ signatures << section unless section.empty?
394
+
395
+ while sections.first && sections.first !~ /^\S/
396
+ sigs = sections.shift
397
+ sigs.split("\n").each do |s|
398
+ signatures << s.strip
399
+ end
400
+ end
401
+
402
+ @signatures = signatures
403
+
404
+ if sections.first && sections.first =~ /^\w+\s*\-/m
405
+ parse_signature_fields(sections.shift)
131
406
  end
132
407
  end
133
408
 
134
- def raises
135
- if tomdoc =~ /^\s*(Raises.+)/m
136
- lines = $1.split("\n")
137
- statements = []
138
-
139
- lines.each do |line|
140
- if line =~ /^\s+/
141
- statements.last << line.squeeze(' ')
142
- else
143
- statements << line
144
- end
409
+ # Subsequent to Signature section there can be field
410
+ # definitions.
411
+ #
412
+ # section - String subsequent to signatures.
413
+ #
414
+ # Returns nothing.
415
+ def parse_signature_fields(section)
416
+ args = []
417
+ last_indent = nil
418
+
419
+ section.split("\n").each do |line|
420
+ next if line.strip.empty?
421
+ indent = line.scan(/^\s*/)[0].to_s.size
422
+
423
+ if last_indent && indent > last_indent
424
+ args.last.description += line.squeeze(" ")
425
+ else
426
+ param, desc = line.split(" - ")
427
+ args << Arg.new(param.strip, desc.strip) if param && desc
145
428
  end
146
429
 
147
- statements
148
- else
149
- []
430
+ last_indent = indent
150
431
  end
432
+
433
+ @signature_fields = args
151
434
  end
435
+
152
436
  end
153
437
  end
@@ -1,3 +1,3 @@
1
1
  module TomDoc
2
- VERSION = '0.2.3'
2
+ VERSION = '0.2.4'
3
3
  end
@@ -46,6 +46,31 @@ comment2
46
46
  # multiplex('Bo', 2)
47
47
  # # => 'BoBo'
48
48
  comment3
49
+
50
+ @comment4 = TomDoc::TomDoc.new(<<comment4)
51
+ # Duplicate some text an abitrary number of times.
52
+ #
53
+ # Yields the Integer index of the iteration.
54
+ #
55
+ # Signature
56
+ #
57
+ # find_by_<field>[_and_<field>...](args)
58
+ #
59
+ # field - A field name.
60
+ comment4
61
+
62
+ @comment5 = TomDoc::TomDoc.new(<<comment5)
63
+ Duplicate some text an abitrary number of times.
64
+
65
+ Yields the Integer index of the iteration.
66
+
67
+ Signature
68
+
69
+ find_by_<field>[_and_<field>...](args)
70
+
71
+ field - A field name.
72
+ comment5
73
+
49
74
  end
50
75
 
51
76
  test "knows when TomDoc is invalid" do
@@ -92,7 +117,7 @@ comment3
92
117
  end
93
118
 
94
119
  test "knows each example" do
95
- assert_equal " multiplex('Bo', 2)\n # => 'BoBo'",
120
+ assert_equal "multiplex('Bo', 2)\n # => 'BoBo'",
96
121
  @comment.examples[1].to_s
97
122
  end
98
123
 
@@ -124,4 +149,26 @@ comment3
124
149
  test "knows what to do when there are no return examples" do
125
150
  assert_equal 0, @comment2.examples.size
126
151
  end
152
+
153
+ test "knows what the method yields" do
154
+ assert_equal "Yields the Integer index of the iteration.", @comment4.yields
155
+ end
156
+
157
+ test "knows if the method has alternate signatures" do
158
+ assert_equal 1, @comment4.signatures.size
159
+ assert_equal "find_by_<field>[_and_<field>...](args)", @comment4.signatures.first
160
+ end
161
+
162
+ test "knows the fields associated with signatures" do
163
+ assert_equal 1, @comment4.signature_fields.size
164
+
165
+ arg = @comment4.signature_fields.first
166
+ assert_equal :field, arg.name
167
+ assert_equal "A field name.", arg.description
168
+ end
169
+
170
+ test "can hande comments without comment marker" do
171
+ assert_equal "Duplicate some text an abitrary number of times.",
172
+ @comment5.description
173
+ end
127
174
  end
metadata CHANGED
@@ -1,62 +1,51 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: tomdoc
3
- version: !ruby/object:Gem::Version
4
- hash: 17
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.4
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 2
9
- - 3
10
- version: 0.2.3
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Tom Preston-Werner
14
9
  - Chris Wanstrath
15
10
  autorequire:
16
11
  bindir: bin
17
12
  cert_chain: []
18
-
19
- date: 2011-06-10 00:00:00 Z
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
13
+ date: 2012-02-22 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
22
16
  name: ruby_parser
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ requirement: &18375600 !ruby/object:Gem::Requirement
25
18
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 7
30
- segments:
31
- - 2
32
- - 0
33
- - 4
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
34
22
  version: 2.0.4
35
23
  type: :runtime
36
- version_requirements: *id001
37
- - !ruby/object:Gem::Dependency
38
- name: colored
39
24
  prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
25
+ version_requirements: *18375600
26
+ - !ruby/object:Gem::Dependency
27
+ name: colored
28
+ requirement: &18375180 !ruby/object:Gem::Requirement
41
29
  none: false
42
- requirements:
43
- - - ">="
44
- - !ruby/object:Gem::Version
45
- hash: 3
46
- segments:
47
- - 0
48
- version: "0"
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
49
34
  type: :runtime
50
- version_requirements: *id002
51
- description: " TomDoc is flexible code documentation with human readers in\n mind. The tomdoc gem is a Ruby library to discover and display\n TomDoc'd methods and classes.\n\n Given a Ruby file with TomDoc'd methods, tomdoc can generate HTML or\n print to the console. You can use it to query up a single method or\n a group of methods, and it's usable from irb.\n\n If you're using TomDoc, tomdoc is for you.\n"
35
+ prerelease: false
36
+ version_requirements: *18375180
37
+ description: ! " TomDoc is flexible code documentation with human readers in\n mind.
38
+ The tomdoc gem is a Ruby library to discover and display\n TomDoc'd methods and
39
+ classes.\n\n Given a Ruby file with TomDoc'd methods, tomdoc can generate HTML
40
+ or\n print to the console. You can use it to query up a single method or\n a group
41
+ of methods, and it's usable from irb.\n\n If you're using TomDoc, tomdoc is for
42
+ you.\n"
52
43
  email: chris@ozmm.org
53
- executables:
44
+ executables:
54
45
  - tomdoc
55
46
  extensions: []
56
-
57
47
  extra_rdoc_files: []
58
-
59
- files:
48
+ files:
60
49
  - README.md
61
50
  - Rakefile
62
51
  - LICENSE
@@ -86,36 +75,27 @@ files:
86
75
  - test/fixtures/simple.rb
87
76
  homepage: http://github.com/defunkt/tomdoc
88
77
  licenses: []
89
-
90
78
  post_install_message:
91
79
  rdoc_options: []
92
-
93
- require_paths:
80
+ require_paths:
94
81
  - lib
95
- required_ruby_version: !ruby/object:Gem::Requirement
82
+ required_ruby_version: !ruby/object:Gem::Requirement
96
83
  none: false
97
- requirements:
98
- - - ">="
99
- - !ruby/object:Gem::Version
100
- hash: 3
101
- segments:
102
- - 0
103
- version: "0"
104
- required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
89
  none: false
106
- requirements:
107
- - - ">="
108
- - !ruby/object:Gem::Version
109
- hash: 3
110
- segments:
111
- - 0
112
- version: "0"
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
113
94
  requirements: []
114
-
115
95
  rubyforge_project:
116
- rubygems_version: 1.8.2
96
+ rubygems_version: 1.8.11
117
97
  signing_key:
118
98
  specification_version: 3
119
99
  summary: A TomDoc library for Ruby.
120
100
  test_files: []
121
-
101
+ has_rdoc: false