bahuvrihi-tap 0.10.7 → 0.10.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/MIT-LICENSE +0 -2
  2. data/README +20 -31
  3. data/bin/rap +18 -8
  4. data/cgi/run.rb +47 -37
  5. data/cmd/console.rb +1 -1
  6. data/cmd/destroy.rb +3 -3
  7. data/cmd/generate.rb +3 -3
  8. data/cmd/manifest.rb +61 -53
  9. data/cmd/run.rb +1 -1
  10. data/doc/Class Reference +119 -110
  11. data/doc/Command Reference +76 -123
  12. data/doc/Syntax Reference +290 -0
  13. data/doc/Tutorial +307 -237
  14. data/lib/tap.rb +1 -12
  15. data/lib/tap/app.rb +46 -71
  16. data/lib/tap/constants.rb +1 -1
  17. data/lib/tap/declarations.rb +110 -100
  18. data/lib/tap/env.rb +141 -173
  19. data/lib/tap/exe.rb +5 -5
  20. data/lib/tap/file_task.rb +2 -2
  21. data/lib/tap/generator/base.rb +0 -4
  22. data/lib/tap/generator/destroy.rb +8 -12
  23. data/lib/tap/generator/generate.rb +19 -14
  24. data/lib/tap/generator/generators/command/command_generator.rb +1 -1
  25. data/lib/tap/generator/generators/config/config_generator.rb +3 -3
  26. data/lib/tap/generator/generators/file_task/file_task_generator.rb +1 -1
  27. data/lib/tap/generator/generators/generator/generator_generator.rb +27 -0
  28. data/lib/tap/generator/generators/generator/templates/task.erb +27 -0
  29. data/lib/tap/generator/generators/root/root_generator.rb +12 -12
  30. data/lib/tap/generator/generators/root/templates/Rakefile +1 -2
  31. data/lib/tap/generator/generators/root/templates/tapfile +11 -8
  32. data/lib/tap/generator/generators/task/task_generator.rb +1 -3
  33. data/lib/tap/generator/generators/task/templates/test.erb +1 -3
  34. data/lib/tap/root.rb +4 -2
  35. data/lib/tap/support/aggregator.rb +16 -3
  36. data/lib/tap/support/assignments.rb +10 -9
  37. data/lib/tap/support/audit.rb +58 -62
  38. data/lib/tap/support/class_configuration.rb +32 -43
  39. data/lib/tap/support/combinator.rb +7 -7
  40. data/lib/tap/support/configurable.rb +13 -14
  41. data/lib/tap/support/configurable_class.rb +6 -30
  42. data/lib/tap/support/configuration.rb +36 -9
  43. data/lib/tap/support/constant.rb +75 -13
  44. data/lib/tap/support/constant_manifest.rb +115 -0
  45. data/lib/tap/support/dependencies.rb +27 -67
  46. data/lib/tap/support/dependency.rb +44 -0
  47. data/lib/tap/support/executable.rb +78 -109
  48. data/lib/tap/support/executable_queue.rb +1 -1
  49. data/lib/tap/support/gems.rb +6 -0
  50. data/lib/tap/support/gems/rack.rb +197 -84
  51. data/lib/tap/support/instance_configuration.rb +29 -3
  52. data/lib/tap/support/intern.rb +46 -0
  53. data/lib/tap/support/join.rb +67 -11
  54. data/lib/tap/support/joins.rb +2 -0
  55. data/lib/tap/support/joins/fork.rb +1 -0
  56. data/lib/tap/support/joins/merge.rb +3 -1
  57. data/lib/tap/support/joins/sequence.rb +2 -2
  58. data/lib/tap/support/joins/switch.rb +3 -1
  59. data/lib/tap/support/joins/sync_merge.rb +6 -0
  60. data/lib/tap/support/lazy_attributes.rb +16 -1
  61. data/lib/tap/support/lazydoc.rb +21 -21
  62. data/lib/tap/support/lazydoc/comment.rb +59 -55
  63. data/lib/tap/support/lazydoc/definition.rb +36 -0
  64. data/lib/tap/support/lazydoc/document.rb +37 -13
  65. data/lib/tap/support/manifest.rb +120 -131
  66. data/lib/tap/support/minimap.rb +90 -0
  67. data/lib/tap/support/node.rb +4 -6
  68. data/lib/tap/support/parser.rb +63 -6
  69. data/lib/tap/support/schema.rb +11 -2
  70. data/lib/tap/support/shell_utils.rb +3 -5
  71. data/lib/tap/support/string_ext.rb +60 -0
  72. data/lib/tap/support/tdoc.rb +2 -2
  73. data/lib/tap/support/templater.rb +29 -15
  74. data/lib/tap/support/validation.rb +22 -11
  75. data/lib/tap/task.rb +155 -156
  76. data/lib/tap/tasks/load.rb +95 -8
  77. data/lib/tap/test/extensions.rb +2 -1
  78. data/lib/tap/test/script_tester.rb +7 -1
  79. data/template/index.erb +39 -32
  80. metadata +13 -13
  81. data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +0 -15
  82. data/lib/tap/patches/rake/rake_test_loader.rb +0 -8
  83. data/lib/tap/patches/rake/testtask.rb +0 -57
  84. data/lib/tap/patches/ruby19/backtrace_filter.rb +0 -51
  85. data/lib/tap/patches/ruby19/parsedate.rb +0 -16
  86. data/lib/tap/spec.rb +0 -42
  87. data/lib/tap/spec/adapter.rb +0 -25
  88. data/lib/tap/spec/inheritable_class_test_root.rb +0 -9
  89. data/lib/tap/support/constant_utils.rb +0 -127
  90. data/lib/tap/support/summary.rb +0 -30
@@ -0,0 +1,46 @@
1
+ module Tap
2
+ module Support
3
+
4
+ # Generates an Intern module for the specified method_name.
5
+ # An Intern module:
6
+ # - adds an accessor for <method_name>_block
7
+ # - overrides <method_name> to call the block
8
+ # - ensures initialize_batch_obj extends the batch object
9
+ # with the same Intern module
10
+ #
11
+ def self.Intern(method_name)
12
+ mod = INTERN_MODULES[method_name.to_sym]
13
+ return mod unless mod == nil
14
+
15
+ mod = INTERN_MODULES[method_name.to_sym] = Module.new
16
+ mod.module_eval %Q{
17
+ attr_accessor :#{method_name}_block
18
+
19
+ def #{method_name}(*inputs)
20
+ raise "no #{method_name} block set" unless #{method_name}_block
21
+ inputs.unshift(self)
22
+
23
+ arity = #{method_name}_block.arity
24
+ n = inputs.length
25
+ unless n == arity || (arity < 0 && (-1-n) <= arity)
26
+ raise ArgumentError.new("wrong number of arguments (\#{n} for \#{arity})")
27
+ end
28
+
29
+ #{method_name}_block.call(*inputs)
30
+ end
31
+
32
+ def initialize_batch_obj(*args)
33
+ super(*args).extend Tap::Support::Intern(:#{method_name})
34
+ end
35
+ }
36
+ mod
37
+ end
38
+
39
+ # An array of already-declared intern modules,
40
+ # keyed by method_name.
41
+ INTERN_MODULES = {}
42
+
43
+ # An Intern module for :process.
44
+ Intern = Support.Intern(:process)
45
+ end
46
+ end
@@ -1,7 +1,19 @@
1
1
  module Tap
2
2
  module Support
3
+
4
+ # Joins create on_complete blocks which link together tasks (or more
5
+ # generally, Executable objects) into workflows. Joins support a
6
+ # variety of configurations which affect how one task passes inputs
7
+ # to subsequent tasks.
8
+ #
9
+ # Joins have a single source and may have multiple targets. See
10
+ # ReverseJoin for joins with a single target and multiple sources.
3
11
  class Join
4
12
  class << self
13
+
14
+ # Create a join between the source and targets. Targets should
15
+ # be an array; if the last member of targets is a hash, it will
16
+ # be used as the configurations for the join.
5
17
  def join(source, targets, &block)
6
18
  options = targets[-1].kind_of?(Hash) ? targets.pop : {}
7
19
  new(options).join(source, targets, &block)
@@ -10,45 +22,76 @@ module Tap
10
22
 
11
23
  include Configurable
12
24
 
25
+ # Causes the join to iterate the results
26
+ # of the source when enquing the targets.
13
27
  config :iterate, false, &c.boolean
28
+
29
+ # Causes the targets to be enqued rather
30
+ # than executed immediately.
14
31
  config :stack, false, &c.boolean
32
+
33
+ # Causes joins to only occur between the
34
+ # explicitly named source and targets,
35
+ # and not their batches.
15
36
  config :unbatched, false, &c.boolean
16
37
 
17
- # An array of workflow flags. All workflow flags are false unless specified.
38
+ # An array of workflow flags. Workflow flags are false unless specified.
18
39
  FLAGS = configurations.keys
19
40
 
20
41
  # An array of the first character in each WORKFLOW_FLAGS.
21
42
  SHORT_FLAGS = FLAGS.collect {|flag| flag.to_s[0,1]}
22
-
23
- def initialize(options)
24
- initialize_config(options)
43
+
44
+ # Initializes a new join with the specified configuration.
45
+ def initialize(config)
46
+ initialize_config(config)
25
47
  end
26
48
 
49
+ # The name of the join, as a symbol. By default
50
+ # name is the basename of the underscored class.
27
51
  def name
28
- self.class.to_s =~ /.*::(.*)$/
29
- $1.underscore.to_sym
52
+ File.basename(self.class.to_s.underscore).to_sym
30
53
  end
31
54
 
55
+ # Creates a join between the source and targets.
56
+ # Must be implemented in subclasses.
57
+ def join(source, targets, &block)
58
+ raise NotImplementedError
59
+ end
60
+
61
+ # A hash of the configurations set to true.
32
62
  def options
33
63
  opts = config.to_hash
34
64
  opts.delete_if {|key, value| value == false }
35
65
  opts
36
66
  end
37
67
 
68
+ # Returns a string like: "#<Join:object_id>"
38
69
  def inspect
39
70
  "#<Join:#{object_id}>"
40
71
  end
41
72
 
42
73
  protected
43
74
 
75
+ # Sets the on_complete block for the specified executable.
76
+ # If unbatched == true, the on_complete block will only
77
+ # be set for the executable; otherwise the on_complete
78
+ # block will be set for executable.batch.
44
79
  def complete(executable, &block)
45
80
  executable.send(unbatched ? :unbatched_on_complete : :on_complete, &block)
46
81
  end
47
82
 
83
+ # Enques the executable with the results, respecting the
84
+ # configuration for self.
85
+ #
86
+ # true false
87
+ # iterate _results are iterated _results are enqued directly
88
+ # stack the executable is enqued the executable is executed
89
+ # unbatched only exectuable is enqued executable.batch is enqued
90
+ #
48
91
  def enq(executable, _results)
49
92
  app = executable.app
50
93
 
51
- results = iterate ? _results._expand : [_results]
94
+ results = iterate ? _results._iterate : [_results]
52
95
  results.each do |_result|
53
96
  if stack
54
97
 
@@ -61,10 +104,10 @@ module Tap
61
104
  else
62
105
 
63
106
  if unbatched
64
- app.execute(executable, _result)
107
+ executable._execute(_result)
65
108
  else
66
109
  executable.batch.each do |e|
67
- app.execute(e, _result)
110
+ e._execute(_result)
68
111
  end
69
112
  end
70
113
 
@@ -73,12 +116,25 @@ module Tap
73
116
  end
74
117
  end
75
118
 
119
+ # Like a Join, but with a single target and multiple sources.
76
120
  class ReverseJoin < Join
121
+ class << self
122
+ # Create a join between the sources and target. Sources should
123
+ # be an array; if the last member of sources is a hash, it will
124
+ # be used as the configurations for the join.
125
+ def join(target, sources, &block)
126
+ options = sources[-1].kind_of?(Hash) ? sources.pop : {}
127
+ new(options).join(target, sources, &block)
128
+ end
129
+ end
130
+
131
+ # Creates a join between the sources and target.
132
+ # Must be implemented in subclasses.
77
133
  def join(target, sources, &block)
78
- options = sources[-1].kind_of?(Hash) ? sources.pop : {}
79
- new(options).join(target, sources, &block)
134
+ raise NotImplementedError
80
135
  end
81
136
 
137
+ # Returns a string like: "#<ReverseJoin:object_id>"
82
138
  def inspect
83
139
  "#<ReverseJoin:#{object_id}>"
84
140
  end
@@ -2,6 +2,8 @@ require 'tap/support/join'
2
2
 
3
3
  module Tap
4
4
  module Support
5
+
6
+ # A module of the standard Join classes supported by Tap.
5
7
  module Joins
6
8
  autoload(:Sequence, 'tap/support/joins/sequence')
7
9
  autoload(:Fork, 'tap/support/joins/fork')
@@ -2,6 +2,7 @@ module Tap
2
2
  module Support
3
3
  module Joins
4
4
 
5
+ # A Fork join passes the results of source to each of the targets.
5
6
  class Fork < Join
6
7
  def join(source, targets)
7
8
  complete(source) do |_result|
@@ -1,7 +1,9 @@
1
1
  module Tap
2
2
  module Support
3
3
  module Joins
4
-
4
+
5
+ # Merge (or simple merge) passes the results of each source to the
6
+ # target without synchronization.
5
7
  class Merge < ReverseJoin
6
8
  def join(target, sources)
7
9
  sources.each do |source|
@@ -1,12 +1,12 @@
1
1
  module Tap
2
2
  module Support
3
3
  module Joins
4
-
4
+
5
+ # A Sequence join simply pass results from one task to the next.
5
6
  class Sequence < Join
6
7
  def join(source, targets)
7
8
  current_task = source
8
9
  targets.each do |next_task|
9
- # simply pass results from one task to the next.
10
10
  complete(current_task) do |_result|
11
11
  yield(_result) if block_given?
12
12
  enq(next_task, _result)
@@ -1,7 +1,9 @@
1
1
  module Tap
2
2
  module Support
3
3
  module Joins
4
-
4
+
5
+ # A Switch join allows a block to determine which target from
6
+ # set of targets will receive the results of the source.
5
7
  class Switch < Join
6
8
  def join(source, targets)
7
9
  complete(source) do |_result|
@@ -1,7 +1,13 @@
1
1
  module Tap
2
2
  module Support
3
+ autoload(:Combinator, 'tap/support/combinator')
4
+
3
5
  module Joins
4
6
 
7
+ # SyncMerge passes the collected results of the sources to the target. The
8
+ # results will not be passed until results from all of the sources are
9
+ # available; results are passed in one group. Similarly, a collision
10
+ # results if a single source completes twice before the group.
5
11
  class SyncMerge < ReverseJoin
6
12
  def join(target, sources)
7
13
 
@@ -2,6 +2,21 @@ require 'tap/support/lazydoc'
2
2
 
3
3
  module Tap
4
4
  module Support
5
+
6
+ # LazyAttributes adds methods to declare class-level accessors
7
+ # for Lazydoc attributes. The source_file for the class must
8
+ # be set manually.
9
+ #
10
+ # # ConstName::key value
11
+ # class ConstName
12
+ # extend LazyAttributes
13
+ #
14
+ # self.source_file = __FILE__
15
+ # lazy_attr :key
16
+ # end
17
+ #
18
+ # ConstName::key.subject # => 'value'
19
+ #
5
20
  module LazyAttributes
6
21
 
7
22
  # The source_file for self. Must be set independently.
@@ -21,7 +36,7 @@ module Tap
21
36
 
22
37
  private
23
38
 
24
- def get_lazy_attr(attribute)
39
+ def get_lazy_attr(attribute) # :nodoc:
25
40
  lazydoc[self.to_s][attribute] ||= Lazydoc::Comment.new
26
41
  end
27
42
 
@@ -8,9 +8,9 @@ module Tap
8
8
  # documentation, constant attributes and code comments. To illustrate,
9
9
  # consider the following:
10
10
  #
11
- # # Sample::key <this is the subject line>
12
- # # a constant attribute content string that
13
- # # can span multiple lines...
11
+ # # Sample::key <value>
12
+ # # This is the comment content. A content
13
+ # # string can span multiple lines...
14
14
  # #
15
15
  # # code.is_allowed
16
16
  # # much.as_in RDoc
@@ -35,12 +35,12 @@ module Tap
35
35
  # Lazydoc::Comment.
36
36
  #
37
37
  # comment = Sample::key
38
- # comment.subject
39
- # # => "<this is the subject line>"
38
+ # comment.value
39
+ # # => "<value>"
40
40
  #
41
41
  # comment.content
42
42
  # # => [
43
- # # ["a constant attribute content string that", "can span multiple lines..."],
43
+ # # ["This is the comment content. A content", "string can span multiple lines..."],
44
44
  # # [""],
45
45
  # # [" code.is_allowed"],
46
46
  # # [" much.as_in RDoc"],
@@ -50,9 +50,9 @@ module Tap
50
50
  # "\n#{'.' * 30}\n" + comment.wrap(30) + "\n#{'.' * 30}\n"
51
51
  # # => %q{
52
52
  # # ..............................
53
- # # a constant attribute content
54
- # # string that can span multiple
55
- # # lines...
53
+ # # This is the comment content.
54
+ # # A content string can span
55
+ # # multiple lines...
56
56
  # #
57
57
  # # code.is_allowed
58
58
  # # much.as_in RDoc
@@ -91,17 +91,17 @@ module Tap
91
91
  # # Const::Name::k@y
92
92
  #
93
93
  # Lazydoc parses a Lazydoc::Comment for each constant attribute by using the
94
- # remainder of the line as a subject and scanning down for content. Scanning
95
- # continues until a non-comment line, an end key, or a new attribute is
96
- # reached; the comment is then stored by constant name and key.
94
+ # remainder of the line as a value (ie subject) and scanning down for content.
95
+ # Scanning continues until a non-comment line, an end key, or a new attribute
96
+ # is reached; the comment is then stored by constant name and key.
97
97
  #
98
98
  # str = %Q{
99
- # # Const::Name::key subject for key
99
+ # # Const::Name::key value for key
100
100
  # # comment for key
101
101
  # # parsed until a
102
102
  # # non-comment line
103
103
  #
104
- # # Const::Name::another subject for another
104
+ # # Const::Name::another value for another
105
105
  # # comment for another
106
106
  # # parsed to an end key
107
107
  # # Const::Name::another-
@@ -112,11 +112,11 @@ module Tap
112
112
  # doc = Lazydoc::Document.new
113
113
  # doc.resolve(str)
114
114
  #
115
- # doc.to_hash {|comment| [comment.subject, comment.to_s] }
115
+ # doc.to_hash {|comment| [comment.value, comment.to_s] }
116
116
  # # => {
117
117
  # # 'Const::Name' => {
118
- # # 'key' => ['subject for key', 'comment for key parsed until a non-comment line'],
119
- # # 'another' => ['subject for another', 'comment for another parsed to an end key']}
118
+ # # 'key' => ['value for key', 'comment for key parsed until a non-comment line'],
119
+ # # 'another' => ['value for another', 'comment for another parsed to an end key']}
120
120
  # # }
121
121
  #
122
122
  # Constant attributes are only parsed from commented lines. To turn off
@@ -128,12 +128,12 @@ module Tap
128
128
  # # :::-
129
129
  # # Const::Name::not_parsed
130
130
  # # :::+
131
- # # Const::Name::parsed subject
131
+ # # Const::Name::parsed value
132
132
  # }
133
133
  #
134
134
  # doc = Lazydoc::Document.new
135
135
  # doc.resolve(str)
136
- # doc.to_hash {|comment| comment.subject } # => {'Const::Name' => {'parsed' => 'subject'}}
136
+ # doc.to_hash {|comment| comment.value } # => {'Const::Name' => {'parsed' => 'value'}}
137
137
  #
138
138
  # To hide attributes from RDoc, make use of the RDoc <tt>:startdoc:</tt>
139
139
  # document modifier like this (note that spaces are added to prevent RDoc
@@ -173,8 +173,8 @@ module Tap
173
173
  # === Code Comments
174
174
  # Code comments are lines registered for parsing if and when a Lazydoc gets
175
175
  # resolved. Unlike constant attributes, the registered line is the comment
176
- # subject and contents are parsed up from it (basically mimicking the
177
- # behavior of RDoc).
176
+ # subject (ie value) and contents are parsed up from it (basically mimicking
177
+ # the behavior of RDoc).
178
178
  #
179
179
  # str = %Q{
180
180
  # # comment lines for
@@ -4,33 +4,32 @@ module Tap
4
4
  module Support
5
5
  module Lazydoc
6
6
  # Comment represents a code comment parsed by Lazydoc. Comments consist
7
- # of a subject and the content of the comment which normally break down
8
- # like this:
7
+ # of a subject and content.
9
8
  #
10
9
  # sample_comment = %Q{
11
- # # this is the content of the comment
10
+ # # this is the content
12
11
  # #
13
- # # which may stretch across
12
+ # # content may stretch across
14
13
  # # multiple lines
15
14
  # this is the subject
16
15
  # }
17
16
  #
18
- # The subject of a comment is the first non-comment line following the
19
- # content, and the content is an array of comment fragments organized
20
- # by line as they would be printed in an output:
17
+ # Normally the subject is the first non-comment line following the content,
18
+ # although in some cases the subject will be manually set to something else
19
+ # (as in a Lazydoc constant attribute). The content is an array of comment
20
+ # fragments organized by line:
21
21
  #
22
22
  # c = Comment.parse(sample_comment)
23
23
  # c.subject # => "this is the subject"
24
24
  # c.content
25
25
  # # => [
26
- # # ["this is the content of the comment"],
26
+ # # ["this is the content"],
27
27
  # # [""],
28
- # # ["which may stretch across", "multiple lines"]]
28
+ # # ["content may stretch across", "multiple lines"]]
29
29
  #
30
- # When pulling comments out of a document, comments may be initialized
31
- # to the line of the subject and then resolved using the document:
30
+ # Comments may be initialized to the subject line and then resolved later:
32
31
  #
33
- # document = %Q{
32
+ # doc = %Q{
34
33
  # module Sample
35
34
  # # this is the content of the comment
36
35
  # # for method_one
@@ -43,26 +42,27 @@ module Tap
43
42
  # end
44
43
  # end}
45
44
  #
46
- # # resolve will split the document, but
47
- # # splitting once beforehand is more efficient
48
- # lines = document.split(/\r?\n/)
49
- #
50
- # c1 = Comment.new(4).resolve(lines)
45
+ # c1 = Comment.new(4).resolve(doc)
51
46
  # c1.subject # => " def method_one"
52
47
  # c1.content # => [["this is the content of the comment", "for method_one"]]
53
48
  #
54
- # c2 = Comment.new(9).resolve(lines)
49
+ # c2 = Comment.new(9).resolve(doc)
55
50
  # c2.subject # => " def method_two"
56
51
  # c2.content # => [["this is the content of the comment", "for method_two"]]
57
- #
52
+ #
53
+ # A Regexp (or Proc) may be used in place of a line number; during resolve,
54
+ # the lines will be scanned and the first matching line will be used.
55
+ #
56
+ # c3 = Comment.new(/def method_two/).resolve(doc)
57
+ # c3.subject # => " def method_two"
58
+ # c3.content # => [["this is the content of the comment", "for method_two"]]
59
+ #
58
60
  class Comment
59
61
 
60
62
  class << self
61
63
 
62
- # Parses the input string into a comment, stopping at end_regexp
63
- # or the first non-comment line. Also parses the next non-comment
64
- # line as the comment subject. Takes a string or a StringScanner
65
- # and returns the new comment.
64
+ # Parses the input string into a comment. Takes a string or a
65
+ # StringScanner and returns the comment.
66
66
  #
67
67
  # comment_string = %Q{
68
68
  # # comments spanning multiple
@@ -73,8 +73,7 @@ module Tap
73
73
  # #
74
74
  # this is the subject line
75
75
  #
76
- # # this line is not parsed as it
77
- # # is after a non-comment line
76
+ # # this line is not parsed
78
77
  # }
79
78
  #
80
79
  # c = Comment.parse(comment_string)
@@ -137,8 +136,9 @@ module Tap
137
136
 
138
137
  # Scan determines if and how to add a line fragment to a comment and
139
138
  # yields the appropriate fragments to the block. Returns true if
140
- # fragments are yielded and false otherwise. A comment's content
141
- # may be built from an array of lines using scan like so:
139
+ # fragments are yielded and false otherwise.
140
+ #
141
+ # Content may be built from an array of lines using scan like so:
142
142
  #
143
143
  # lines = [
144
144
  # "# comments spanning multiple",
@@ -154,7 +154,6 @@ module Tap
154
154
  # c = Comment.new
155
155
  # lines.each do |line|
156
156
  # break unless Comment.scan(line) do |fragment|
157
- # # c.unshift will also work if building in reverse
158
157
  # c.push(fragment)
159
158
  # end
160
159
  # end
@@ -197,37 +196,34 @@ module Tap
197
196
  # the appropriate objects to add the fragment to a
198
197
  # comment
199
198
  def categorize(fragment, indent) # :nodoc:
200
- case
201
- when fragment == indent
202
- # empty comment line
203
- yield [""]
204
- yield []
205
- when indent.empty?
206
- # continuation line
207
- yield fragment.rstrip
208
- else
209
- # indented line
210
- yield [fragment.rstrip]
211
- yield []
212
- end
213
- end
199
+ case
200
+ when fragment == indent
201
+ # empty comment line
202
+ yield [""]
203
+ yield []
204
+ when indent.empty?
205
+ # continuation line
206
+ yield fragment.rstrip
207
+ else
208
+ # indented line
209
+ yield [fragment.rstrip]
210
+ yield []
211
+ end
212
+ end
214
213
  end
215
214
 
216
- # An array of comment fragments organized into
217
- # lines as they would be printed in an output.
218
- # Ex: [["fragments", "of line", "one"],
219
- # ["fragments", "of line", "two"]]
215
+ # An array of comment fragments organized into lines
220
216
  attr_reader :content
221
217
 
222
218
  # The subject of the comment (normally set to the next
223
219
  # non-comment line after the content ends; ie the line
224
- # that would receive the comment in RDoc documentation).
220
+ # that would receive the comment in RDoc documentation)
225
221
  attr_accessor :subject
226
222
 
227
223
  # Returns the line number for the subject line, if known.
228
224
  # Although normally an integer, line_number may be
229
225
  # set to a Regexp or Proc to dynamically determine
230
- # itself during resolve.
226
+ # the subject line during resolve
231
227
  attr_accessor :line_number
232
228
 
233
229
  def initialize(line_number=nil)
@@ -235,6 +231,16 @@ module Tap
235
231
  @subject = nil
236
232
  @line_number = line_number
237
233
  end
234
+
235
+ # Alias for subject
236
+ def value
237
+ subject
238
+ end
239
+
240
+ # Alias for subject=
241
+ def value=(value)
242
+ self.subject = value
243
+ end
238
244
 
239
245
  # Pushes the fragment onto the last line array of content. If the
240
246
  # fragment is an array itself then it will be pushed onto content
@@ -379,13 +385,11 @@ module Tap
379
385
  # c.subject # => " def method_one"
380
386
  # c.content # => [["this is the content of the comment", "for method_one"]]
381
387
  #
382
- # Notes:
383
- # - resolve is a good hook for post-processing in subclasses
384
- # - lines may be an array or a string; string inputs are split
385
- # into lines along newline boundaries.
388
+ # Lines may be an array or a string; string inputs are split into an
389
+ # array along newline boundaries.
386
390
  #
387
- # === late-evaluation line numbers
388
- # The line_number used by resolve may be determined directly from
391
+ # === dynamic line numbers
392
+ # The line_number used by resolve may be determined dynamically from
389
393
  # lines by setting line_number to a Regexp and Proc. In the case
390
394
  # of a Regexp, the first line matching the regexp is used:
391
395
  #
@@ -404,7 +408,7 @@ module Tap
404
408
  # c.subject # => " def method_two"
405
409
  # c.content # => [["this is the content of the comment", "for method_two"]]
406
410
  #
407
- # As shown in the examples, in both cases the late-evaluation
411
+ # As shown in the examples, in both cases the dynamically determined
408
412
  # line_number overwrites the Regexp or Proc.
409
413
  def resolve(lines)
410
414
  lines = lines.split(/\r?\n/) if lines.kind_of?(String)