tap 0.7.9 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History +28 -0
- data/MIT-LICENSE +1 -1
- data/README +71 -43
- data/Rakefile +81 -64
- data/Tutorial +235 -0
- data/bin/tap +80 -44
- data/lib/tap.rb +41 -12
- data/lib/tap/app.rb +243 -246
- data/lib/tap/file_task.rb +357 -118
- data/lib/tap/generator.rb +88 -29
- data/lib/tap/generator/generators/config/config_generator.rb +4 -2
- data/lib/tap/generator/generators/config/templates/config.erb +1 -2
- data/lib/tap/generator/generators/file_task/file_task_generator.rb +3 -18
- data/lib/tap/generator/generators/file_task/templates/task.erb +22 -15
- data/lib/tap/generator/generators/file_task/templates/test.erb +13 -2
- data/{test/test/inference_methods/test_assert_files_exist/input/input_1.txt → lib/tap/generator/generators/generator/USAGE} +0 -0
- data/lib/tap/generator/generators/generator/generator_generator.rb +21 -0
- data/lib/tap/generator/generators/generator/templates/generator.erb +23 -0
- data/lib/tap/generator/generators/generator/templates/usage.erb +1 -0
- data/{test/test/inference_methods/test_assert_files_exist/input/input_2.txt → lib/tap/generator/generators/package/USAGE} +0 -0
- data/lib/tap/generator/generators/package/package_generator.rb +38 -0
- data/lib/tap/generator/generators/package/templates/package.erb +186 -0
- data/lib/tap/generator/generators/root/root_generator.rb +14 -9
- data/lib/tap/generator/generators/root/templates/Rakefile +20 -14
- data/{test/test/inference_methods/test_infer_glob/expected/file.yml → lib/tap/generator/generators/root/templates/ReadMe.txt} +0 -0
- data/lib/tap/generator/generators/root/templates/tap.yml +82 -0
- data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +0 -1
- data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +2 -1
- data/{test/test/inference_methods/test_infer_glob/expected/file_1.txt → lib/tap/generator/generators/script/USAGE} +0 -0
- data/lib/tap/generator/generators/script/script_generator.rb +17 -0
- data/lib/tap/generator/generators/script/templates/script.erb +42 -0
- data/lib/tap/generator/generators/task/task_generator.rb +1 -1
- data/lib/tap/generator/generators/task/templates/task.erb +24 -16
- data/lib/tap/generator/generators/task/templates/test.erb +13 -17
- data/lib/tap/generator/generators/workflow/templates/task.erb +10 -10
- data/lib/tap/generator/generators/workflow/templates/test.erb +1 -1
- data/lib/tap/generator/generators/workflow/workflow_generator.rb +3 -18
- data/lib/tap/root.rb +108 -146
- data/lib/tap/script.rb +362 -0
- data/lib/tap/script/console.rb +28 -0
- data/lib/tap/script/destroy.rb +13 -1
- data/lib/tap/script/generate.rb +13 -1
- data/lib/tap/script/run.rb +100 -57
- data/lib/tap/support/batch_queue.rb +0 -3
- data/lib/tap/support/logger.rb +6 -3
- data/lib/tap/support/rake.rb +54 -0
- data/lib/tap/support/task_configuration.rb +169 -0
- data/lib/tap/support/tdoc.rb +198 -0
- data/lib/tap/support/tdoc/config_attr.rb +338 -0
- data/lib/tap/support/tdoc/tdoc_html_generator.rb +38 -0
- data/lib/tap/support/tdoc/tdoc_html_template.rb +42 -0
- data/lib/tap/support/versions.rb +33 -1
- data/lib/tap/task.rb +339 -227
- data/lib/tap/test.rb +86 -128
- data/lib/tap/test/env_vars.rb +16 -5
- data/lib/tap/test/file_methods.rb +373 -0
- data/lib/tap/test/subset_methods.rb +299 -180
- data/lib/tap/version.rb +2 -1
- data/lib/tap/workflow.rb +2 -0
- data/test/app/lib/app_test_task.rb +1 -0
- data/test/app_test.rb +327 -83
- data/test/check/binding_eval.rb +23 -0
- data/test/check/define_method_check.rb +22 -0
- data/test/check/dependencies_check.rb +175 -0
- data/test/check/inheritance_check.rb +22 -0
- data/test/file_task_test.rb +524 -291
- data/test/{test/inference_methods/test_infer_glob/expected/file_2.txt → root/glob/one.txt} +0 -0
- data/test/root/glob/two.txt +0 -0
- data/test/root_test.rb +330 -262
- data/test/script_test.rb +194 -0
- data/test/support/audit_test.rb +5 -2
- data/test/support/combinator_test.rb +10 -10
- data/test/support/rake_test.rb +35 -0
- data/test/support/task_configuration_test.rb +272 -0
- data/test/support/tdoc_test.rb +363 -0
- data/test/support/templater_test.rb +2 -2
- data/test/support/versions_test.rb +32 -0
- data/test/tap_test_helper.rb +39 -0
- data/test/task_base_test.rb +115 -0
- data/test/task_class_test.rb +56 -4
- data/test/task_execute_test.rb +29 -0
- data/test/task_test.rb +89 -70
- data/test/test/env_vars_test.rb +48 -0
- data/test/test/{inference_methods → file_methods}/test_assert_expected/expected/file.txt +0 -0
- data/test/test/{inference_methods → file_methods}/test_assert_expected/expected/folder/file.txt +0 -0
- data/test/test/{inference_methods → file_methods}/test_assert_expected/input/file.txt +0 -0
- data/test/test/{inference_methods → file_methods}/test_assert_expected/input/folder/file.txt +0 -0
- data/test/test/file_methods/test_assert_files_exist/input/input_1.txt +0 -0
- data/test/test/file_methods/test_assert_files_exist/input/input_2.txt +0 -0
- data/test/test/file_methods/test_assert_output_files_equal/expected/one.txt +1 -0
- data/test/test/file_methods/test_assert_output_files_equal/expected/two.txt +1 -0
- data/test/test/file_methods/test_assert_output_files_equal/input/one.txt +1 -0
- data/test/test/file_methods/test_assert_output_files_equal/input/two.txt +1 -0
- data/test/test/{inference_methods → file_methods}/test_file_compare/expected/output_1.txt +0 -0
- data/test/test/{inference_methods → file_methods}/test_file_compare/expected/output_2.txt +0 -0
- data/test/test/{inference_methods → file_methods}/test_file_compare/input/input_1.txt +0 -0
- data/test/test/{inference_methods → file_methods}/test_file_compare/input/input_2.txt +0 -0
- data/test/test/file_methods/test_infer_glob/expected/file.yml +0 -0
- data/test/test/file_methods/test_infer_glob/expected/file_1.txt +0 -0
- data/test/test/file_methods/test_infer_glob/expected/file_2.txt +0 -0
- data/test/test/file_methods/test_method_glob/expected/file.yml +0 -0
- data/test/test/file_methods/test_method_glob/expected/file_1.txt +0 -0
- data/test/test/file_methods/test_method_glob/expected/file_2.txt +0 -0
- data/test/test/{inference_methods → file_methods}/test_yml_compare/expected/output_1.yml +0 -0
- data/test/test/{inference_methods → file_methods}/test_yml_compare/expected/output_2.yml +0 -0
- data/test/test/{inference_methods → file_methods}/test_yml_compare/input/input_1.yml +0 -0
- data/test/test/{inference_methods → file_methods}/test_yml_compare/input/input_2.yml +0 -0
- data/test/test/file_methods_test.rb +204 -0
- data/test/test/subset_methods_test.rb +93 -33
- data/test/test/test_assert_expected_result_files/expected/task/name/a.txt +1 -0
- data/test/test/test_assert_expected_result_files/expected/task/name/b.txt +1 -0
- data/test/test/test_assert_expected_result_files/input/a.txt +1 -0
- data/test/test/test_assert_expected_result_files/input/b.txt +1 -0
- data/test/test/test_file_task_test/expected/one.txt +1 -0
- data/test/test/test_file_task_test/expected/two.txt +1 -0
- data/test/test/test_file_task_test/input/one.txt +1 -0
- data/test/test/test_file_task_test/input/two.txt +1 -0
- data/test/test_test.rb +143 -3
- data/test/workflow_test.rb +2 -0
- data/vendor/rails_generator.rb +56 -0
- data/vendor/rails_generator/base.rb +263 -0
- data/vendor/rails_generator/commands.rb +581 -0
- data/vendor/rails_generator/generated_attribute.rb +42 -0
- data/vendor/rails_generator/lookup.rb +209 -0
- data/vendor/rails_generator/manifest.rb +53 -0
- data/vendor/rails_generator/options.rb +143 -0
- data/vendor/rails_generator/scripts.rb +83 -0
- data/vendor/rails_generator/scripts/destroy.rb +7 -0
- data/vendor/rails_generator/scripts/generate.rb +7 -0
- data/vendor/rails_generator/scripts/update.rb +12 -0
- data/vendor/rails_generator/simple_logger.rb +46 -0
- data/vendor/rails_generator/spec.rb +44 -0
- metadata +180 -196
- data/lib/tap/generator/generators/root/templates/app.yml +0 -19
- data/lib/tap/generator/generators/root/templates/config/process_tap_request.yml +0 -4
- data/lib/tap/generator/generators/root/templates/lib/process_tap_request.rb +0 -26
- data/lib/tap/generator/generators/root/templates/public/images/nav.jpg +0 -0
- data/lib/tap/generator/generators/root/templates/public/stylesheets/color.css +0 -57
- data/lib/tap/generator/generators/root/templates/public/stylesheets/layout.css +0 -108
- data/lib/tap/generator/generators/root/templates/public/stylesheets/normalize.css +0 -40
- data/lib/tap/generator/generators/root/templates/public/stylesheets/typography.css +0 -21
- data/lib/tap/generator/generators/root/templates/server/config/environment.rb +0 -60
- data/lib/tap/generator/generators/root/templates/server/lib/tasks/clear_database_prerequisites.rake +0 -5
- data/lib/tap/generator/generators/root/templates/server/test/test_helper.rb +0 -53
- data/lib/tap/script/server.rb +0 -12
- data/lib/tap/support/rap.rb +0 -38
- data/lib/tap/test/inference_methods.rb +0 -298
- data/test/task/config/task_with_config.yml +0 -1
- data/test/test/inference_methods_test.rb +0 -311
data/lib/tap/support/logger.rb
CHANGED
@@ -2,20 +2,23 @@ require 'logger'
|
|
2
2
|
|
3
3
|
module Tap
|
4
4
|
module Support
|
5
|
+
|
6
|
+
# == UNDER CONSTRUCTION
|
5
7
|
# Logger provides methods to extend Logger objects.
|
6
8
|
#
|
7
9
|
# The output format is designed to look nice in a command prompt, but provide useful information
|
8
10
|
# if directed at a log file. The Logger output format is like:
|
9
11
|
#
|
10
|
-
# I[datetime]
|
11
|
-
|
12
|
+
# I[datetime] action message
|
13
|
+
#--
|
12
14
|
# The first letter ('I' - INFO) indicates the severity of the message, next comes the datetime of the
|
13
15
|
# log, the type of log message, then the message itself. Specify the log type and message like:
|
14
16
|
#
|
15
17
|
# logger.type "message"
|
16
18
|
#
|
17
19
|
# Typed logging occurs through +method_missing+. Any type is possible so long as the logger doesn't
|
18
|
-
#
|
20
|
+
# already have a method of the input type.
|
21
|
+
#++
|
19
22
|
module Logger
|
20
23
|
Format = " %s[%s] %18s %s\n"
|
21
24
|
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rake'
|
2
|
+
|
3
|
+
module Rake # :nodoc:
|
4
|
+
# Modifies Rake::Task to behave like a Tap::Task.
|
5
|
+
class Task # :nodoc:
|
6
|
+
alias_method(:tap_original_execute, :execute)
|
7
|
+
alias_method(:tap_original_invoke, :invoke)
|
8
|
+
alias_method(:tap_original_initialize, :initialize)
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
tap_original_initialize(*args)
|
12
|
+
self.extend Tap::Task::Base
|
13
|
+
self.extend InstanceMethods
|
14
|
+
end
|
15
|
+
|
16
|
+
def invoke
|
17
|
+
@lock.synchronize do
|
18
|
+
if application.options.trace
|
19
|
+
puts "** Invoke #{name} #{format_trace_flags}"
|
20
|
+
end
|
21
|
+
return if @already_invoked
|
22
|
+
@already_invoked = true
|
23
|
+
invoke_prerequisites
|
24
|
+
tap_original_execute if needed?
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module InstanceMethods # :nodoc:
|
29
|
+
|
30
|
+
def iterate=(input)
|
31
|
+
raise "iterate cannot be set to true for Rake tasks." if input == true
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def on_execute(audited_inputs)
|
37
|
+
invoke
|
38
|
+
audited_inputs._record(self, nil)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
module Tap
|
45
|
+
module Support
|
46
|
+
# == UNDER CONSTRUCTION
|
47
|
+
module Rake
|
48
|
+
|
49
|
+
def task(td, config=nil)
|
50
|
+
Object::Rake.application.lookup(td) || super
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
module Tap
|
2
|
+
module Support
|
3
|
+
# == UNDER CONSTRUCTION
|
4
|
+
#
|
5
|
+
# TaskConfiguration holds the class configurations defined in a Tap::Task.
|
6
|
+
# The configurations are stored as an array of declarations like:
|
7
|
+
# [name, default, msg, declaration_class]. In addition, TaskConfiguration
|
8
|
+
# collapse the array of declarations into a hash, which acts as the default
|
9
|
+
# task configuration.
|
10
|
+
#
|
11
|
+
# Storing metadata about the configurations, such as the declaration_class,
|
12
|
+
# allows the creation of more user-friendly configuration files and facilitates
|
13
|
+
# incorporation into command-line applications.
|
14
|
+
#
|
15
|
+
# In general, users will not have to interact with TaskConfigurations directly.
|
16
|
+
#
|
17
|
+
# == Example
|
18
|
+
#
|
19
|
+
# class BaseTask < Tap::Task
|
20
|
+
# class_configurations [:one, 1]
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# BaseTask.configurations.hash # => {:one => 1}
|
24
|
+
#
|
25
|
+
# class SubTask < BaseTask
|
26
|
+
# class_configurations(
|
27
|
+
# [:one, 'one', "the first configuration"],
|
28
|
+
# [:two, 'two', "the second configuration"])
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# SubTask.configurations.hash # => {:one => 'one', :two => 'two'}
|
32
|
+
#
|
33
|
+
# Now you can see how the comments and declaring classes get used in the
|
34
|
+
# configuration files. Note that configuration keys are stringified
|
35
|
+
# for clarity (this is ok -- they will be symbolized when loaded by a
|
36
|
+
# task).
|
37
|
+
#
|
38
|
+
# [BaseTask.configurations.format_yaml]
|
39
|
+
# # BaseTask configuration
|
40
|
+
# one: 1
|
41
|
+
#
|
42
|
+
# [SubTask.configurations.format_yaml]
|
43
|
+
# # BaseTask configuration
|
44
|
+
# one: one # the first configuration
|
45
|
+
#
|
46
|
+
# # SubTask configuration
|
47
|
+
# two: two # the second configuration
|
48
|
+
#
|
49
|
+
class TaskConfiguration
|
50
|
+
attr_reader :declarations, :default, :attributes
|
51
|
+
|
52
|
+
include Enumerable
|
53
|
+
|
54
|
+
def initialize
|
55
|
+
@declarations = {}
|
56
|
+
@default = {}
|
57
|
+
@attributes = {}
|
58
|
+
end
|
59
|
+
|
60
|
+
def dup
|
61
|
+
# ensure the duplication does not pass along
|
62
|
+
# new references to the same objects
|
63
|
+
another = TaskConfiguration.new
|
64
|
+
another.declarations = self.declarations.dup
|
65
|
+
another.default = self.default.dup
|
66
|
+
another.attributes = self.attributes.dup
|
67
|
+
another
|
68
|
+
end
|
69
|
+
|
70
|
+
def empty?
|
71
|
+
@declaration.empty?
|
72
|
+
end
|
73
|
+
|
74
|
+
def declared?(key)
|
75
|
+
default.has_key?(key.to_sym)
|
76
|
+
end
|
77
|
+
|
78
|
+
def declare(key, declaration_class)
|
79
|
+
key = key.to_sym
|
80
|
+
|
81
|
+
# Check if the key is already declared...
|
82
|
+
return if declared?(key)
|
83
|
+
|
84
|
+
# Add a declaration array if no declaration have been
|
85
|
+
# created for the class and append the key
|
86
|
+
(declarations[declaration_class] ||= [declarations.length]) << key
|
87
|
+
default[key] = nil
|
88
|
+
attributes[key] = {}
|
89
|
+
end
|
90
|
+
|
91
|
+
def set(key, value, attributes={})
|
92
|
+
key = key.to_sym
|
93
|
+
raise "configurations cannot be set until they are declared" unless declared?(key)
|
94
|
+
|
95
|
+
default[key] = value
|
96
|
+
self.attributes[key].merge!(attributes)
|
97
|
+
end
|
98
|
+
|
99
|
+
def each # :yields: declaration_class, key, default, attributes
|
100
|
+
declarations.each_pair do |declaration_class, keys|
|
101
|
+
keys[1..-1].each do |key|
|
102
|
+
yield(declaration_class, key, default[key], attributes[key])
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Nicely formats the configurations into yaml with messages and
|
108
|
+
# declaration class divisions.
|
109
|
+
def format_yaml
|
110
|
+
lines = []
|
111
|
+
declarations.each_pair do |declaration_class, keys|
|
112
|
+
lines << "# #{declaration_class} configuration#{keys.length > 2 ? 's' : ''}"
|
113
|
+
|
114
|
+
class_name = declaration_class.to_s
|
115
|
+
class_path = class_name.underscore
|
116
|
+
source_file = Dependencies.search_for_file(class_path)
|
117
|
+
|
118
|
+
Tap::Support::TDoc.document(source_file)
|
119
|
+
class_doc = Tap::Support::TDoc[declaration_class]
|
120
|
+
configurations = (class_doc == nil ? [] : class_doc.configurations)
|
121
|
+
|
122
|
+
keys[1..-1].each do |key|
|
123
|
+
value = default[key]
|
124
|
+
attribs = attributes[key]
|
125
|
+
message = ""
|
126
|
+
configurations.each do |config|
|
127
|
+
if config.name == key.to_s
|
128
|
+
message = config.comment
|
129
|
+
break
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# yaml adds a header and a final newline which should be removed:
|
134
|
+
# {'key' => 'value'}.to_yaml # => "--- \nkey: value\n"
|
135
|
+
# {'key' => 'value'}.to_yaml[5...-1] # => "key: value"
|
136
|
+
yaml = {key.to_s => value}.to_yaml[5...-1]
|
137
|
+
#yaml = "##{yaml}" if value.nil?
|
138
|
+
|
139
|
+
lines << case
|
140
|
+
when message == nil || message.empty?
|
141
|
+
# if there is no message, simply add the yaml
|
142
|
+
yaml
|
143
|
+
when yaml !~ /\r?\n/ && message !~ /\r?\n/ && yaml.length < 20 && message.length < 30
|
144
|
+
# shorthand ONLY if the config and message can be expressed in a single line
|
145
|
+
message = message.gsub(/^#\s*/, "")
|
146
|
+
"%-20s # %s" % [yaml, message]
|
147
|
+
else
|
148
|
+
# comment out new lines and add the message
|
149
|
+
message = message.gsub(/\n#\s*/, "\n# ")
|
150
|
+
lines << "# #{message}"
|
151
|
+
yaml
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# add a spacer line
|
156
|
+
lines << ""
|
157
|
+
end
|
158
|
+
|
159
|
+
lines.join("\n")
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
protected
|
164
|
+
|
165
|
+
attr_writer :declarations, :default, :attributes
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require 'tap/support/tdoc/config_attr'
|
2
|
+
require 'singleton'
|
3
|
+
|
4
|
+
module Tap
|
5
|
+
module Support
|
6
|
+
|
7
|
+
# == Overview
|
8
|
+
# TDoc hooks into and extends RDoc to make task documentation available for command line
|
9
|
+
# applications as well as for inclusion in RDoc html. In particular, TDoc makes available
|
10
|
+
# documentation for Task configurations, when they are present. TDoc provides an extension
|
11
|
+
# to the standard RDoc HTMLGenerator and template.
|
12
|
+
#
|
13
|
+
# == Usage
|
14
|
+
# To generate task documentation with configuration information, TDoc must be loaded and
|
15
|
+
# the appropriate flags passed to rdoc . Essentially what you want is:
|
16
|
+
#
|
17
|
+
# % rdoc --fmt tdoc --template tap/support/tdoc/tdoc_html_template [file_names....]
|
18
|
+
#
|
19
|
+
# Unfortunately, there is no way to load or require a file into the rdoc utility directly; the
|
20
|
+
# above code causes an 'Invalid output formatter' error. However, TDoc is easy to utilize
|
21
|
+
# from a Rake::RDocTask:
|
22
|
+
#
|
23
|
+
# require 'rake'
|
24
|
+
# require 'rake/rdoctask'
|
25
|
+
#
|
26
|
+
# desc 'Generate documentation.'
|
27
|
+
# Rake::RDocTask.new(:rdoc) do |rdoc|
|
28
|
+
# require 'tap/support/tdoc'
|
29
|
+
# rdoc.template = 'tap/support/tdoc/tdoc_html_template'
|
30
|
+
# rdoc.options << '--fmt' << 'tdoc'
|
31
|
+
#
|
32
|
+
# # specify whatever else you need
|
33
|
+
# # rdoc.rdoc_files.include(...)
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# Now execute the rake task like:
|
37
|
+
#
|
38
|
+
# % rake rdoc
|
39
|
+
#
|
40
|
+
# TDoc may also be utilized programatically, but you should be aware that RDoc in Ruby
|
41
|
+
# can raise errors and/or cause namespace conflicts (see below).
|
42
|
+
#
|
43
|
+
# == Implementation
|
44
|
+
# RDoc is a beast to utilize in a non-standard way. One way to make RDoc parse unexpected
|
45
|
+
# flags like 'config_accessor' or the 'c' config specifier is to use the '--accessor' option
|
46
|
+
# (see 'rdoc --help' or the RDoc documentation for more details).
|
47
|
+
#
|
48
|
+
# TDoc hooks into the '--accessor' parsing process to pull out configuration attributes and
|
49
|
+
# format them into their own Configuration section on an RDoc html page. When 'tdoc' is
|
50
|
+
# specified as an rdoc option, TDoc in effect sets accessor flags for all the standard Task
|
51
|
+
# configuration methods, and then extends the RDoc::RubyParser handle these specially.
|
52
|
+
#
|
53
|
+
# If 'tdoc' is not specified as the rdoc format, TDoc does not affect the RDoc output.
|
54
|
+
# Similarly, the configuration attributes will not appear in the output unless you specify a
|
55
|
+
# template that utilizes them.
|
56
|
+
#
|
57
|
+
# == Namespace conflicts
|
58
|
+
# RDoc creates a namespace conflict with other libraries that define RubyToken and RubyLex
|
59
|
+
# in the Object namespace (the prime example being IRB). TDoc checks for such a conflict
|
60
|
+
# and redfines the RDoc RubyToken and RubyLex within the RDoc namespace. Essentially:
|
61
|
+
#
|
62
|
+
# RubyToken => RDoc::RubyToken
|
63
|
+
# RubyLex => RDoc::RubyLex
|
64
|
+
#
|
65
|
+
# The redefinition should not affect the existing RubyToken and RubyLex constants, but if
|
66
|
+
# you directly use the RDoc versions after loading TDoc, you should be aware that they must
|
67
|
+
# be accessed through the new constants. Unfortunatley the trick is not seamless. The RDoc
|
68
|
+
# RubyLex makes a few calls to the RubyLex class method 'debug?'... these will be issued to
|
69
|
+
# the existing RubyLex method and not RDoc::RubyLex.debug?
|
70
|
+
#
|
71
|
+
# In addition, because of the RubyLex calls, the RDoc::RubyLex cannot be fully hidden when
|
72
|
+
# TDoc is loaded before the conflicting RubyLex; you cannot load TDoc before loading IRB
|
73
|
+
# without raising warnings. I hope to submit a patch for RDoc to stop this nonsense in the
|
74
|
+
# future.
|
75
|
+
#
|
76
|
+
# On the plus side, you can now access/use RDoc within irb by requiring 'tap/support/tdoc'.
|
77
|
+
#
|
78
|
+
class TDoc
|
79
|
+
include Singleton
|
80
|
+
|
81
|
+
attr_accessor :stats, :options, :documented_files, :load_paths
|
82
|
+
|
83
|
+
def initialize
|
84
|
+
reinitialize
|
85
|
+
end
|
86
|
+
|
87
|
+
def reinitialize(argv=['--fmt', 'tdoc', '--quiet'])
|
88
|
+
@documented_files = []
|
89
|
+
@tl = RDoc::TopLevel::reset
|
90
|
+
@stats = RDoc::Stats.new
|
91
|
+
@options = Options.instance
|
92
|
+
@options.parse(argv, RDoc::RDoc::GENERATORS)
|
93
|
+
@load_paths = $:
|
94
|
+
end
|
95
|
+
|
96
|
+
class << self
|
97
|
+
|
98
|
+
def search_for_files(path_suffix)
|
99
|
+
# modified from 'activesupport/dependencies'
|
100
|
+
path_suffix = path_suffix + '.rb' unless path_suffix.ends_with? '.rb'
|
101
|
+
|
102
|
+
files = instance.load_paths.collect do |root|
|
103
|
+
path = File.join(root, path_suffix)
|
104
|
+
File.file?(path) ? path : nil
|
105
|
+
end.compact
|
106
|
+
end
|
107
|
+
|
108
|
+
def search_for_source_files(klass)
|
109
|
+
source_files = search_for_files(klass.to_s.underscore)
|
110
|
+
while klass.superclass.kind_of?(Tap::Task)
|
111
|
+
klass = klass.superclass
|
112
|
+
break if klass.configurations.empty?
|
113
|
+
source_files.concat(search_for_files(klass.to_s.underscore))
|
114
|
+
end
|
115
|
+
|
116
|
+
source_files.uniq
|
117
|
+
end
|
118
|
+
|
119
|
+
def document(*filepaths)
|
120
|
+
filepaths.each do |filepath|
|
121
|
+
next if filepath == nil || instance.documented_files.include?(filepath) || !File.exists?(filepath)
|
122
|
+
|
123
|
+
tl = RDoc::TopLevel.new(filepath)
|
124
|
+
parser = RDoc::RubyParser.new(tl, filepath, File.read(filepath), instance.options, instance.stats)
|
125
|
+
parser.scan
|
126
|
+
instance.documented_files << filepath
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def find_class_or_module_named(name)
|
131
|
+
RDoc::TopLevel.all_classes_and_modules.each do |c|
|
132
|
+
res = c.find_class_or_module_named(name)
|
133
|
+
return res if res
|
134
|
+
end
|
135
|
+
nil
|
136
|
+
end
|
137
|
+
|
138
|
+
def [](klass)
|
139
|
+
name = klass.to_s
|
140
|
+
res = find_class_or_module_named(name)
|
141
|
+
|
142
|
+
# If no result was found, try to document a sourcefile
|
143
|
+
# from the standard filepath and search again
|
144
|
+
if res == nil
|
145
|
+
source_files = klass.respond_to?(:source_files) ? klass.source_files : []
|
146
|
+
source_files = search_for_source_files(klass) if source_files.empty?
|
147
|
+
|
148
|
+
unless source_files.empty?
|
149
|
+
document(*source_files)
|
150
|
+
res = find_class_or_module_named(name)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
res
|
155
|
+
end
|
156
|
+
|
157
|
+
def usage(program_file, sections=[], keep_section_headers=false)
|
158
|
+
comment = []
|
159
|
+
File.open(program_file) do |file|
|
160
|
+
while line = file.gets
|
161
|
+
case line
|
162
|
+
when /^\s*$/
|
163
|
+
# skip leading blank lines
|
164
|
+
comment.empty? ? next : break
|
165
|
+
when /^\s*# ?(.*)/m
|
166
|
+
comment << $1
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
unless sections.empty?
|
172
|
+
sections_hash = {}
|
173
|
+
current_section = nil
|
174
|
+
comment.each do |line|
|
175
|
+
case line
|
176
|
+
when /^s*=+(.*)/
|
177
|
+
current_section = []
|
178
|
+
current_section << line if keep_section_headers
|
179
|
+
sections_hash[$1.strip] = current_section
|
180
|
+
else
|
181
|
+
current_section << line unless current_section.nil?
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
comment = []
|
186
|
+
sections.each do |section|
|
187
|
+
next unless sections_hash.has_key?(section)
|
188
|
+
comment.concat(sections_hash[section])
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
comment.join('')
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|