bahuvrihi-tap 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. data/History +69 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +119 -0
  4. data/bin/tap +114 -0
  5. data/cmd/console.rb +42 -0
  6. data/cmd/destroy.rb +16 -0
  7. data/cmd/generate.rb +16 -0
  8. data/cmd/run.rb +126 -0
  9. data/doc/Class Reference +362 -0
  10. data/doc/Command Reference +153 -0
  11. data/doc/Tutorial +237 -0
  12. data/lib/tap.rb +32 -0
  13. data/lib/tap/app.rb +720 -0
  14. data/lib/tap/constants.rb +8 -0
  15. data/lib/tap/env.rb +640 -0
  16. data/lib/tap/file_task.rb +547 -0
  17. data/lib/tap/generator/base.rb +109 -0
  18. data/lib/tap/generator/destroy.rb +37 -0
  19. data/lib/tap/generator/generate.rb +61 -0
  20. data/lib/tap/generator/generators/command/command_generator.rb +21 -0
  21. data/lib/tap/generator/generators/command/templates/command.erb +32 -0
  22. data/lib/tap/generator/generators/config/config_generator.rb +26 -0
  23. data/lib/tap/generator/generators/config/templates/doc.erb +12 -0
  24. data/lib/tap/generator/generators/config/templates/nodoc.erb +8 -0
  25. data/lib/tap/generator/generators/file_task/file_task_generator.rb +27 -0
  26. data/lib/tap/generator/generators/file_task/templates/file.txt +11 -0
  27. data/lib/tap/generator/generators/file_task/templates/result.yml +6 -0
  28. data/lib/tap/generator/generators/file_task/templates/task.erb +33 -0
  29. data/lib/tap/generator/generators/file_task/templates/test.erb +29 -0
  30. data/lib/tap/generator/generators/root/root_generator.rb +55 -0
  31. data/lib/tap/generator/generators/root/templates/Rakefile +86 -0
  32. data/lib/tap/generator/generators/root/templates/gemspec +27 -0
  33. data/lib/tap/generator/generators/root/templates/tapfile +8 -0
  34. data/lib/tap/generator/generators/root/templates/test/tap_test_helper.rb +3 -0
  35. data/lib/tap/generator/generators/root/templates/test/tap_test_suite.rb +5 -0
  36. data/lib/tap/generator/generators/root/templates/test/tapfile_test.rb +15 -0
  37. data/lib/tap/generator/generators/task/task_generator.rb +27 -0
  38. data/lib/tap/generator/generators/task/templates/task.erb +14 -0
  39. data/lib/tap/generator/generators/task/templates/test.erb +21 -0
  40. data/lib/tap/generator/manifest.rb +14 -0
  41. data/lib/tap/patches/rake/rake_test_loader.rb +8 -0
  42. data/lib/tap/patches/rake/testtask.rb +55 -0
  43. data/lib/tap/patches/ruby19/backtrace_filter.rb +51 -0
  44. data/lib/tap/patches/ruby19/parsedate.rb +16 -0
  45. data/lib/tap/root.rb +581 -0
  46. data/lib/tap/support/aggregator.rb +55 -0
  47. data/lib/tap/support/assignments.rb +172 -0
  48. data/lib/tap/support/audit.rb +418 -0
  49. data/lib/tap/support/batchable.rb +47 -0
  50. data/lib/tap/support/batchable_class.rb +107 -0
  51. data/lib/tap/support/class_configuration.rb +194 -0
  52. data/lib/tap/support/command_line.rb +98 -0
  53. data/lib/tap/support/comment.rb +270 -0
  54. data/lib/tap/support/configurable.rb +114 -0
  55. data/lib/tap/support/configurable_class.rb +296 -0
  56. data/lib/tap/support/configuration.rb +122 -0
  57. data/lib/tap/support/constant.rb +70 -0
  58. data/lib/tap/support/constant_utils.rb +127 -0
  59. data/lib/tap/support/declarations.rb +111 -0
  60. data/lib/tap/support/executable.rb +111 -0
  61. data/lib/tap/support/executable_queue.rb +82 -0
  62. data/lib/tap/support/framework.rb +71 -0
  63. data/lib/tap/support/framework_class.rb +199 -0
  64. data/lib/tap/support/instance_configuration.rb +147 -0
  65. data/lib/tap/support/lazydoc.rb +428 -0
  66. data/lib/tap/support/manifest.rb +89 -0
  67. data/lib/tap/support/run_error.rb +39 -0
  68. data/lib/tap/support/shell_utils.rb +71 -0
  69. data/lib/tap/support/summary.rb +30 -0
  70. data/lib/tap/support/tdoc.rb +404 -0
  71. data/lib/tap/support/tdoc/tdoc_html_generator.rb +38 -0
  72. data/lib/tap/support/tdoc/tdoc_html_template.rb +42 -0
  73. data/lib/tap/support/templater.rb +180 -0
  74. data/lib/tap/support/validation.rb +410 -0
  75. data/lib/tap/support/versions.rb +97 -0
  76. data/lib/tap/task.rb +259 -0
  77. data/lib/tap/tasks/dump.rb +56 -0
  78. data/lib/tap/tasks/rake.rb +93 -0
  79. data/lib/tap/test.rb +37 -0
  80. data/lib/tap/test/env_vars.rb +29 -0
  81. data/lib/tap/test/file_methods.rb +377 -0
  82. data/lib/tap/test/script_methods.rb +144 -0
  83. data/lib/tap/test/subset_methods.rb +420 -0
  84. data/lib/tap/test/tap_methods.rb +237 -0
  85. data/lib/tap/workflow.rb +187 -0
  86. metadata +145 -0
@@ -0,0 +1,109 @@
1
+ require 'tap/generator/manifest'
2
+
3
+ module Tap
4
+ module Generator
5
+ class Base < Tap::Task
6
+ class << self
7
+ def lazydoc(resolve=false, args_method=:manifest)
8
+ if resolve
9
+ lazydoc = super(false)
10
+ lazydoc.resolve(nil, /^\s*def\s+#{args_method}(\((.*?)\))?/) do |comment, match|
11
+ args = match[2].to_s.split(',').collect do |arg|
12
+ arg = arg.strip.upcase
13
+ case arg
14
+ when /^&/ then nil
15
+ when /^\*/ then arg[1..-1] + "..."
16
+ else arg
17
+ end
18
+ end
19
+ args.shift
20
+
21
+ comment.subject = args.join(', ')
22
+ lazydoc.default_attributes['args'] ||= comment
23
+ end
24
+ end
25
+
26
+ super(false)
27
+ end
28
+
29
+ def help
30
+ Tap::Support::Templater.new(DEFAULT_HELP_TEMPLATE,
31
+ :task_class => self,
32
+ :manifest => lazydoc(true)[to_s]['generator'] || Tap::Support::Comment.new
33
+ ).build
34
+ end
35
+ end
36
+
37
+ Constant = Tap::Support::Constant
38
+
39
+ config :pretend, false, &c.flag # Run but rollback any changes.
40
+ config :force, false, &c.flag # Overwrite files that already exist.
41
+ config :skip, false, &c.flag # Skip files that already exist.
42
+
43
+ attr_accessor :file_task, :template_dir, :target_dir
44
+
45
+ def initialize(config={}, name=nil, app=App.instance)
46
+ super(config, name, app)
47
+
48
+ @file_task = Tap::FileTask.new
49
+ @template_dir = File.dirname(self.class.source_file) + '/templates'
50
+ end
51
+
52
+ def process(*argv)
53
+ actions = []
54
+ manifest(Manifest.new(actions), *argv)
55
+
56
+ iterate(actions) do |action, args, block|
57
+ send(action, *args, &block)
58
+ end
59
+
60
+ @target_dir = nil
61
+ file_task.added_files
62
+ end
63
+
64
+ def log_relative(action, path)
65
+ log(action, app.relative_filepath(Dir.pwd, path))
66
+ end
67
+
68
+ def manifest(m, *argv)
69
+ raise NotImplementedError
70
+ end
71
+
72
+ def iterate(action)
73
+ raise NotImplementedError
74
+ end
75
+
76
+ def directory(target, options={})
77
+ raise NotImplementedError
78
+ end
79
+
80
+ def file(target, options={})
81
+ raise NotImplementedError
82
+ end
83
+
84
+ def directories(root, targets, options={})
85
+ directory(root)
86
+ targets.each do |target|
87
+ directory(File.join(root, target), options)
88
+ end
89
+ end
90
+
91
+ def template(target, source, attributes={}, options={})
92
+ template_path = File.expand_path(source, template_dir)
93
+ templater = Support::Templater.new(File.read(template_path), attributes)
94
+
95
+ file(target, options) do |file|
96
+ file << templater.build
97
+ end
98
+ end
99
+
100
+ def template_files
101
+ Dir.glob(template_dir + "/**/*").sort.each do |source|
102
+ target = Tap::Root.relative_filepath(template_dir, source)
103
+ yield(source, target)
104
+ end
105
+ end
106
+
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,37 @@
1
+ module Tap
2
+ module Generator
3
+ module Destroy
4
+ def iterate(actions)
5
+ actions.reverse_each {|action| yield(action) }
6
+ end
7
+
8
+ def directory(target, options={})
9
+ target = File.expand_path(target, target_dir)
10
+
11
+ case
12
+ when !File.exists?(target)
13
+ log_relative :missing, target
14
+ when !file_task.dir_empty?(target)
15
+ log_relative 'not empty', target
16
+ else
17
+ log_relative :rm, target
18
+ file_task.added_files << File.expand_path(target)
19
+ file_task.rmdir(target) unless pretend
20
+ end
21
+ end
22
+
23
+ def file(target, options={})
24
+ target = File.expand_path(target, target_dir)
25
+
26
+ if File.exists?(target)
27
+ log_relative :rm, target
28
+ file_task.added_files << File.expand_path(target)
29
+ file_task.rm(target) unless pretend
30
+ else
31
+ log_relative :missing, target
32
+ end
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,61 @@
1
+ module Tap
2
+ module Generator
3
+ module Generate
4
+ def iterate(actions)
5
+ actions.each {|action| yield(action) }
6
+ end
7
+
8
+ def directory(target, options={})
9
+ target = File.expand_path(target, target_dir)
10
+
11
+ if File.exists?(target)
12
+ log_relative :exists, target
13
+ else
14
+ log_relative :create, target
15
+ file_task.mkdir(target) unless pretend
16
+ end
17
+ end
18
+
19
+ def file(target, options={})
20
+ target = File.expand_path(target, target_dir)
21
+
22
+ case
23
+ when !File.exists?(target)
24
+ log_relative :create, target
25
+ # should check for identical...
26
+ when force_file_collision?(target)
27
+ log_relative :force, target
28
+ else
29
+ log_relative :skip, target
30
+ return
31
+ end
32
+
33
+ unless pretend
34
+ file_task.prepare(target)
35
+ File.open(target, "wb") {|file| yield(file) if block_given? }
36
+ end
37
+ end
38
+
39
+ # Ask the user interactively whether to force collision.
40
+ def force_file_collision?(target)
41
+ return false if skip
42
+ return true if force
43
+
44
+ $stdout.print "overwrite #{target}? [Ynaiq] "
45
+ $stdout.flush
46
+ case $stdin.gets
47
+ when /a/i
48
+ self.force = true
49
+ when /i/i
50
+ self.skip = true
51
+ when /q/i
52
+ $stdout.puts "aborting #{name}"
53
+ raise SystemExit
54
+ when /n/i then false
55
+ when /y/i then true
56
+ else force_file_collision?(destination)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,21 @@
1
+ module Tap::Generator::Generators
2
+
3
+ # :startdoc::generator a new tap command
4
+ #
5
+ # Generates a new tap command under the cmd directory. The
6
+ # new command can be run from the command line using:
7
+ #
8
+ # % tap <command>
9
+ #
10
+ class CommandGenerator < Tap::Generator::Base
11
+
12
+ def manifest(m, command_name)
13
+ m.directory app['cmd']
14
+
15
+ template_files do |source, target|
16
+ m.template app.filepath('cmd', "#{command_name}.rb"), source, :command_name => command_name
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,32 @@
1
+ # tap <%= command_name %> {options} ARGS...
2
+ #
3
+ # The default command simply prints the input arguments
4
+ # and application information, then exits.
5
+ #
6
+
7
+ env = Tap::Env.instance
8
+ app = Tap::App.instance
9
+
10
+ #
11
+ # handle options
12
+ #
13
+
14
+ OptionParser.new do |opts|
15
+ opts.separator ""
16
+ opts.separator "options:"
17
+
18
+ opts.on("-h", "--help", "Show this message") do
19
+ opts.banner = Tap::Support::CommandLine.usage(__FILE__)
20
+ puts opts
21
+ exit
22
+ end
23
+
24
+ end.parse!(ARGV)
25
+
26
+
27
+ #
28
+ # add your script code here
29
+ #
30
+
31
+ puts "Received: #{ARGV.join(', ')}"
32
+ puts app.info
@@ -0,0 +1,26 @@
1
+ module Tap::Generator::Generators
2
+
3
+ # :startdoc::generator a config file for a task
4
+ #
5
+ # Generates a new config file for a task. The configurations, defaults,
6
+ # and documentation is determined from the task source file.
7
+ class ConfigGenerator < Tap::Generator::Base
8
+
9
+ config :doc, true, &c.switch # include documentation in the config
10
+
11
+ def env
12
+ Tap::Env.instance
13
+ end
14
+
15
+ def manifest(m, name, config_name=name)
16
+ const = env.search(:tasks, name) or raise "unknown task: #{name}"
17
+ task_class = const.constantize or raise "unknown task: #{name}"
18
+
19
+ m.directory app['config']
20
+ m.file app.filepath('config', config_name + '.yml') do |file|
21
+ task_class.configurations.format_str((doc ? :doc : :nodoc), file)
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,12 @@
1
+ ###############################################################################
2
+ # <%= receiver %> configuration<%= configurations.length > 1 ? 's' : '' %>
3
+ ###############################################################################
4
+ <% configurations.each do |key, config| %>
5
+
6
+ <% Comment.wrap(config.desc.to_s.split(/\r?\n/), 50, 2).each do |line| %>
7
+ # <%= line %>
8
+ <% end %>
9
+ <%= config.default == nil ? '#' : '' %><%= yamlize({key.to_s => config.default}) %>
10
+
11
+ <% end %>
12
+
@@ -0,0 +1,8 @@
1
+ ###############################################################################
2
+ # <%= receiver %> configuration<%= configurations.length > 1 ? 's' : '' %>
3
+ ###############################################################################
4
+ <% configurations.each do |key, config| %>
5
+ <%= config.default == nil ? '#' : ''%><%= yamlize({key.to_s => config.default}) %>
6
+
7
+ <% end %>
8
+
@@ -0,0 +1,27 @@
1
+ require 'tap/generator/generators/task/task_generator'
2
+
3
+ module Tap::Generator::Generators
4
+
5
+ # :startdoc::generator a file_task and test
6
+ #
7
+ # Generates a new Tap::FileTask and associated test files.
8
+ class FileTaskGenerator < TaskGenerator
9
+
10
+ def manifest(m, const_name)
11
+ const = super
12
+
13
+ if test
14
+ test_dir = app.filepath('test', const.path, "test_#{const.basename}")
15
+
16
+ m.directories test_dir, %W{
17
+ input
18
+ expected
19
+ }
20
+
21
+ m.template File.join(test_dir, 'input/file.txt'), "file.txt", :const => const, :test_dir => test_dir
22
+ m.template File.join(test_dir, 'expected/result.yml'), "result.yml", :const => const, :test_dir => test_dir
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ absquatulate - verb: This amusing, vivid, and expressive word is a bit of a jocular, contrived slang. To absquatulate is to decamp, to scram, to take off in a hell of a hurry like a fugitive heading into the woods.
2
+
3
+ algorism - noun: This is the name of the Arabic numbering system, using the figures 1 to 9 plus the zero. The derivation is from Middle Latin algorismus, from the Arabic al (the) plus Khuwarizmi, the surname of a ninth-century Arabic mathematician. Algorithm is sometimes used as a synonym, but is also used to designate a set of rules for the solution of a mathematical problem in a finite number of steps. These words are entirely unrelated to algolagnia, with its very different meaning and derivation.
4
+
5
+ defenestration - verb: Defenestration is the act of throwing someone (yes, someone!) or something out of a window. To defenestrate a person or thing is to engage in this activity - a strange one indeed, since these words are more commonly applied to situations where what is thrown out of the window is a person, rather than a thing. It is surprising, in view of what must be the infrequency of this type of activity, that there exists word for it, but then, there exists a word for just about everything.
6
+
7
+ macaronic - adj: This peculiar word, a jocular concoction from macaroni, is applied, in a narrow sense, to language characterized by a mixture of Latin and non-Latin words, or by non-Latin words given phony Latin endings; in a broader sense, to prose or verse composed of any mixture of languages; in its broadest sense, to anything mixed or jumbled.
8
+
9
+ trumpery - noun: Trumpery is worthless stuff.
10
+
11
+ usufruct - noun: Usufruct is a term used in law primarily, to denote one's right to enjoy the use and benefits flowing from the use of another's property, without the ownership of it and without the right to harm or waste or destroy it.
@@ -0,0 +1,6 @@
1
+ ---
2
+ - 111
3
+ - 155
4
+ - 123
5
+ - 125
6
+ - 56
@@ -0,0 +1,33 @@
1
+ <% redirect do |target| %># <%= const.name %>::manifest <replace with manifest summary>
2
+ # <replace with command line description>
3
+
4
+ # <%= const.const_name %> Documentation
5
+ # This example FileTask counts the specified letters
6
+ # in a source file and writes the counts to a target
7
+ # file as YAML.
8
+ #
9
+ class <%= const.const_name %> < Tap::FileTask
10
+
11
+ # <config file documentation>
12
+ config :letters, ['a','e','i','o','u'], &c.array # a list of letters to count
13
+
14
+ def process(source, target)
15
+
16
+ # prepare ensures the parent directory for target
17
+ # exists and, if necessary, backs up the existing
18
+ # target file (which is restored on error)
19
+ prepare(target)
20
+
21
+ # now perform the task...
22
+ str = File.read(source)
23
+ letter_count = letters.collect do |letter|
24
+ str.count(letter)
25
+ end
26
+
27
+ File.open(target, "wb") do |file|
28
+ file << letter_count.to_yaml
29
+ end
30
+
31
+ target
32
+ end
33
+ end <% module_nest(const.nesting, ' ') { target } end %>
@@ -0,0 +1,29 @@
1
+ require File.join(File.dirname(__FILE__), '<%= '../' * const.nesting_depth %>tap_test_helper.rb')
2
+ require '<%= const.path %>'
3
+
4
+ class <%= const.name %>Test < Test::Unit::TestCase
5
+ acts_as_tap_test
6
+
7
+ def test_<%= const.basename %>
8
+ # Use assert_files to test file transform tasks. The block
9
+ # recieves the method input files and compares the results
10
+ # to the method expected files.
11
+
12
+ # Generated files are often placed in method output, as it
13
+ # is cleaned up each test. To keep output files, set the
14
+ # KEEP_OUTPUTS variable:
15
+ # % rake test keep_outputs=true
16
+
17
+ t = <%= const.name %>.new
18
+ assert_files do |input_files|
19
+ input_files.each do |source|
20
+ target = method_filepath(:output, 'result.yml')
21
+ t.enq(source, target)
22
+ end
23
+
24
+ app.run
25
+ app.results(t)
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,55 @@
1
+ require 'tap/root'
2
+
3
+ module Tap::Generator::Generators
4
+
5
+ # :startdoc::generator a basic tap directory structure
6
+ #
7
+ # Generates a tap root directory structure:
8
+ #
9
+ # root
10
+ # |- Rakefile
11
+ # |- lib
12
+ # |- sample.gemspec
13
+ # |- tap.yml
14
+ # |- tapfile.rb
15
+ # `- test
16
+ # |- tap_test_helper.rb
17
+ # |- tap_test_suite.rb
18
+ # `- tapfile_test.rb
19
+ #
20
+ class RootGenerator < Tap::Generator::Base
21
+
22
+ # ::args ROOT, PROJECT_NAME=basename(ROOT)
23
+ def manifest(m, root, project_name=File.basename(root))
24
+ project_name = 'project' if project_name == '.'
25
+ r = Tap::Root.new(root)
26
+
27
+ m.directory r.root
28
+ m.directory r['lib']
29
+
30
+ template_files do |source, target|
31
+ case
32
+ when File.directory?(source)
33
+ m.directory r[target]
34
+ when target == 'gemspec'
35
+ m.template r[project_name + '.gemspec'], source, :project_name => project_name
36
+ when target == 'tapfile'
37
+ m.template r['tapfile.rb'], source, :project_name => project_name
38
+ else
39
+ m.template r[target], source, :project_name => project_name
40
+ end
41
+ end
42
+
43
+ # m.file(r['tap.yml']) do |file|
44
+ # Tap::App.configurations.format_str(:doc, file) do |templater|
45
+ # next unless templater.receiver == Tap::Root
46
+ #
47
+ # templater.configurations.each do |(key, config)|
48
+ # config.default = nil if key.to_s == 'root'
49
+ # end
50
+ # end
51
+ # Tap::Env.configurations.format_str(:doc, file)
52
+ # end
53
+ end
54
+ end
55
+ end