tap 0.19.0 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/History +100 -45
  2. data/MIT-LICENSE +1 -1
  3. data/README +95 -51
  4. data/bin/tap +11 -57
  5. data/bin/tapexe +84 -0
  6. data/doc/API +91 -139
  7. data/doc/Configuration +93 -0
  8. data/doc/Examples/Command Line +10 -42
  9. data/doc/Examples/Tapfile +124 -0
  10. data/doc/Ruby to Ruby +87 -0
  11. data/doc/Workflow Syntax +185 -0
  12. data/lib/tap.rb +74 -5
  13. data/lib/tap/app.rb +217 -310
  14. data/lib/tap/app/api.rb +44 -23
  15. data/lib/tap/app/queue.rb +11 -12
  16. data/lib/tap/app/stack.rb +4 -4
  17. data/lib/tap/declarations.rb +200 -0
  18. data/lib/tap/declarations/context.rb +31 -0
  19. data/lib/tap/declarations/description.rb +33 -0
  20. data/lib/tap/env.rb +133 -779
  21. data/lib/tap/env/cache.rb +87 -0
  22. data/lib/tap/env/constant.rb +94 -39
  23. data/lib/tap/env/path.rb +71 -0
  24. data/lib/tap/join.rb +42 -78
  25. data/lib/tap/joins/gate.rb +85 -0
  26. data/lib/tap/joins/switch.rb +4 -2
  27. data/lib/tap/joins/sync.rb +3 -3
  28. data/lib/tap/middleware.rb +5 -5
  29. data/lib/tap/middlewares/debugger.rb +18 -58
  30. data/lib/tap/parser.rb +115 -183
  31. data/lib/tap/root.rb +162 -239
  32. data/lib/tap/signal.rb +72 -0
  33. data/lib/tap/signals.rb +20 -2
  34. data/lib/tap/signals/class_methods.rb +38 -43
  35. data/lib/tap/signals/configure.rb +19 -0
  36. data/lib/tap/signals/help.rb +5 -7
  37. data/lib/tap/signals/load.rb +49 -0
  38. data/lib/tap/signals/module_methods.rb +1 -0
  39. data/lib/tap/task.rb +46 -275
  40. data/lib/tap/tasks/dump.rb +21 -16
  41. data/lib/tap/tasks/list.rb +184 -0
  42. data/lib/tap/tasks/load.rb +4 -4
  43. data/lib/tap/tasks/prompt.rb +128 -0
  44. data/lib/tap/tasks/signal.rb +42 -0
  45. data/lib/tap/tasks/singleton.rb +35 -0
  46. data/lib/tap/tasks/stream.rb +64 -0
  47. data/lib/tap/utils.rb +83 -0
  48. data/lib/tap/version.rb +2 -2
  49. data/lib/tap/workflow.rb +124 -0
  50. data/tap.yml +0 -0
  51. metadata +59 -24
  52. data/cmd/console.rb +0 -43
  53. data/cmd/manifest.rb +0 -118
  54. data/cmd/run.rb +0 -145
  55. data/doc/Examples/Workflow +0 -40
  56. data/lib/tap/app/node.rb +0 -29
  57. data/lib/tap/env/context.rb +0 -61
  58. data/lib/tap/env/gems.rb +0 -63
  59. data/lib/tap/env/manifest.rb +0 -179
  60. data/lib/tap/env/minimap.rb +0 -308
  61. data/lib/tap/intern.rb +0 -50
  62. data/lib/tap/joins.rb +0 -9
  63. data/lib/tap/prompt.rb +0 -36
  64. data/lib/tap/root/utils.rb +0 -220
  65. data/lib/tap/root/versions.rb +0 -138
  66. data/lib/tap/signals/signal.rb +0 -68
@@ -0,0 +1,35 @@
1
+ require 'tap/task'
2
+
3
+ module Tap
4
+ module Tasks
5
+ class Singleton < Tap::Task
6
+ class << self
7
+ def cache
8
+ @cache ||= {}
9
+ end
10
+
11
+ def new(*args)
12
+ obj = super
13
+ cache[obj.signature] ||= obj
14
+ end
15
+ end
16
+
17
+ attr_reader :cache
18
+ attr_reader :signature
19
+
20
+ def initialize(config={}, app=Tap::App.current)
21
+ @signature = [config.dup, app].freeze
22
+ super(config, app)
23
+ reset
24
+ end
25
+
26
+ def call(input)
27
+ cache.has_key?(input) ? cache[input] : cache[input] = super
28
+ end
29
+
30
+ def reset
31
+ @cache = {}
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,64 @@
1
+ require 'tap/tasks/load'
2
+
3
+ module Tap
4
+ module Tasks
5
+
6
+ # Stream recurrently loads data from $stdin by requeing self until an
7
+ # end-of-file is reached. This behavior is useful for creating tasks
8
+ # that load a bit of data from an IO, send it into a workflow, and then
9
+ # repeat.
10
+ #
11
+ # The eof cutoff can be modified using complete? method. Streaming will
12
+ # stop when complete? returns true. For instance, this is a prompt task:
13
+ #
14
+ # class Prompt < Tap::Tasks::Stream
15
+ # config :exit_seq, "\n"
16
+ #
17
+ # def load(io)
18
+ # if io.eof?
19
+ # nil
20
+ # else
21
+ # io.readline
22
+ # end
23
+ # end
24
+ #
25
+ # def complete?(io, line)
26
+ # line == nil || line == exit_seq
27
+ # end
28
+ # end
29
+ #
30
+ class Stream < Load
31
+
32
+ # Loads data from io. Process will open the input io object, load
33
+ # a result, then check to see if the loading is complete (using the
34
+ # complete? method). Unless loading is complete, process will enque
35
+ # io to self. Process will close io when loading is complete, provided
36
+ # use_close or file is specified.
37
+ def process(io=$stdin)
38
+ io = open(io)
39
+ result = load(io)
40
+
41
+ if complete?(io, result)
42
+ if use_close || file
43
+ close(io)
44
+ end
45
+ else
46
+ reque(io)
47
+ end
48
+
49
+ result
50
+ end
51
+
52
+ # Returns true by default. Override in subclasses to allow recurrent
53
+ # loading (see process).
54
+ def complete?(io, last)
55
+ io.eof?
56
+ end
57
+
58
+ # Reques self with io to the top of the queue.
59
+ def reque(io)
60
+ app.pq(self, [io])
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,83 @@
1
+ require 'tempfile'
2
+
3
+ module Tap
4
+
5
+ #
6
+ # == Windows
7
+ # MSDOS has command line length limits specific to the version of Windows being
8
+ # run (from http://www.ss64.com/nt/cmd.html):
9
+ #
10
+ # Windows NT:: 256 characters
11
+ # Windows 2000:: 2046 characters
12
+ # Windows XP:: 8190 characters
13
+ #
14
+ # Commands longer than these limits fail, usually with something like: 'the input
15
+ # line is too long'
16
+ module Utils
17
+ module_function
18
+
19
+ def shellsplit(line, comment="#")
20
+ words = []
21
+ field = ''
22
+ line.scan(/\G\s*(?>([^\s\\\'\"]+)|'([^\']*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|\z)?/m) do
23
+ |word, sq, dq, esc, garbage, sep|
24
+ raise ArgumentError, "Unmatched double quote: #{line.inspect}" if garbage
25
+ break if word == comment
26
+ field << (word || sq || (dq || esc).gsub(/\\(?=.)/, ''))
27
+ if sep
28
+ words << field
29
+ field = ''
30
+ end
31
+ end
32
+ words
33
+ end
34
+
35
+ # Sets the specified ENV variables and returns the *current* env.
36
+ # If replace is true, current ENV variables are replaced; otherwise
37
+ # the new env variables are simply added to the existing set.
38
+ def set_env(env={}, replace=false)
39
+ current_env = {}
40
+ ENV.each_pair do |key, value|
41
+ current_env[key] = value
42
+ end
43
+
44
+ ENV.clear if replace
45
+
46
+ env.each_pair do |key, value|
47
+ if value.nil?
48
+ ENV.delete(key)
49
+ else
50
+ ENV[key] = value
51
+ end
52
+ end if env
53
+
54
+ current_env
55
+ end
56
+
57
+ # Sets the specified ENV variables for the duration of the block.
58
+ # If replace is true, current ENV variables are replaced; otherwise
59
+ # the new env variables are simply added to the existing set.
60
+ #
61
+ # Returns the block return.
62
+ def with_env(env={}, replace=false)
63
+ current_env = nil
64
+ begin
65
+ current_env = set_env(env, replace)
66
+ yield
67
+ ensure
68
+ if current_env
69
+ set_env(current_env, true)
70
+ end
71
+ end
72
+ end
73
+
74
+ def sh_escape(str)
75
+ str.to_s.gsub("'", "\\\\'").gsub(";", '\\;')
76
+ end
77
+
78
+ # Run the command with system and raise an error if it fails.
79
+ def sh(*cmd)
80
+ system(*cmd) or raise "Command failed with status (#{$?.exitstatus}): [#{cmd.join(' ')}]"
81
+ end
82
+ end
83
+ end
@@ -1,6 +1,6 @@
1
1
  module Tap
2
- MAJOR = 0
3
- MINOR = 19
2
+ MAJOR = 1
3
+ MINOR = 3
4
4
  TINY = 0
5
5
 
6
6
  VERSION="#{MAJOR}.#{MINOR}.#{TINY}"
@@ -0,0 +1,124 @@
1
+ require 'tap/task'
2
+
3
+ module Tap
4
+ class Workflow < Task
5
+ class << self
6
+ protected
7
+
8
+ # Defines a task subclass with the specified configurations and process
9
+ # block. During initialization the subclass is instantiated and made
10
+ # accessible through the name method.
11
+ #
12
+ # Defined tasks may be configured during through config, or directly
13
+ # through the instance; in effect you get tasks with nested configs which
14
+ # can greatly facilitate workflows.
15
+ #
16
+ # class AddALetter < Tap::Task
17
+ # config :letter, 'a'
18
+ # def process(input); input << letter; end
19
+ # end
20
+ #
21
+ # class AlphabetSoup < Tap::Task
22
+ # define :a, AddALetter, {:letter => 'a'}
23
+ # define :b, AddALetter, {:letter => 'b'}
24
+ # define :c, AddALetter, {:letter => 'c'}
25
+ #
26
+ # def process
27
+ # sequence(a, b, c)
28
+ # [a, c]
29
+ # end
30
+ # end
31
+ #
32
+ # AlphabetSoup.new.process # => 'abc'
33
+ #
34
+ # i = AlphabetSoup.new(:a => {:letter => 'x'}, :b => {:letter => 'y'}, :c => {:letter => 'z'})
35
+ # i.process # => 'xyz'
36
+ #
37
+ # i.config[:a] = {:letter => 'p'}
38
+ # i.config[:b][:letter] = 'q'
39
+ # i.c.letter = 'r'
40
+ # i.process # => 'pqr'
41
+ #
42
+ # ==== Usage
43
+ #
44
+ # Define is basically the equivalent of:
45
+ #
46
+ # class Sample < Tap::Task
47
+ # Name = baseclass.subclass(config, &block)
48
+ #
49
+ # # accesses an instance of Name
50
+ # attr_reader :name
51
+ #
52
+ # # register name as a config, but with a
53
+ # # non-standard reader and writer
54
+ # config :name, {}, {:reader => :name_config, :writer => :name_config=}.merge(options)
55
+ #
56
+ # # reader for name.config
57
+ # def name_config; ...; end
58
+ #
59
+ # # reconfigures name with input
60
+ # def name_config=(input); ...; end
61
+ #
62
+ # def initialize(*args)
63
+ # super
64
+ # @name = Name.new(config[:name])
65
+ # end
66
+ # end
67
+ #
68
+ # Note the following:
69
+ # * define will set a constant like name.camelize
70
+ # * the block defines the process method in the subclass
71
+ # * three methods are created by define: name, name_config, name_config=
72
+ #
73
+ def define(name, baseclass=Tap::Task, configs={}, options={}, &block)
74
+ # define the subclass
75
+ subclass = Class.new(baseclass)
76
+ configs.each_pair do |key, value|
77
+ subclass.send(:config, key, value)
78
+ end
79
+
80
+ if block_given?
81
+ # prevent lazydoc registration of the process method
82
+ subclass.registered_methods.delete(:process)
83
+ subclass.send(:define_method, :process, &block)
84
+ end
85
+
86
+ # register documentation
87
+ # TODO: register subclass in documentation
88
+ options[:desc] ||= Lazydoc.register_caller(Lazydoc::Trailer, 1)
89
+
90
+ # add the configuration
91
+ nest(name, subclass, {:const_name => name.to_s.camelize}.merge!(options))
92
+ end
93
+ end
94
+
95
+ attr_reader :entry_point
96
+ attr_reader :exit_point
97
+
98
+ def initialize(config={}, app=Tap::App.current)
99
+ super
100
+ @entry_point, @exit_point = process
101
+ end
102
+
103
+ def call(input)
104
+ output = nil
105
+
106
+ if exit_point
107
+ joins = exit_point.joins
108
+
109
+ collector = lambda do |result|
110
+ output = result
111
+ joins.delete(collector)
112
+ end
113
+
114
+ joins << collector
115
+ end
116
+
117
+ if entry_point
118
+ app.exe(entry_point, input)
119
+ end
120
+
121
+ output
122
+ end
123
+ end
124
+ end
data/tap.yml ADDED
File without changes
metadata CHANGED
@@ -1,7 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.0
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 3
8
+ - 0
9
+ version: 1.3.0
5
10
  platform: ruby
6
11
  authors:
7
12
  - Simon Chiang
@@ -9,19 +14,37 @@ autorequire:
9
14
  bindir: bin
10
15
  cert_chain: []
11
16
 
12
- date: 2009-12-05 00:00:00 -07:00
17
+ date: 2010-05-02 00:00:00 -06:00
13
18
  default_executable:
14
19
  dependencies:
15
20
  - !ruby/object:Gem::Dependency
16
21
  name: configurable
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ - 7
30
+ - 0
31
+ version: 0.7.0
17
32
  type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: tap-test
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
20
38
  requirements:
21
39
  - - ">="
22
40
  - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ - 6
44
+ - 0
23
45
  version: 0.6.0
24
- version:
46
+ type: :development
47
+ version_requirements: *id002
25
48
  description:
26
49
  email: simon.a.chiang@gmail.com
27
50
  executables:
@@ -33,54 +56,64 @@ extra_rdoc_files:
33
56
  - MIT-LICENSE
34
57
  - History
35
58
  - doc/API
59
+ - doc/Workflow Syntax
60
+ - doc/Ruby to Ruby
36
61
  - doc/Examples/Command Line
37
- - doc/Examples/Workflow
62
+ - doc/Examples/Tapfile
63
+ - doc/Configuration
38
64
  files:
39
- - cmd/console.rb
40
- - cmd/manifest.rb
41
- - cmd/run.rb
65
+ - bin/tapexe
42
66
  - lib/tap.rb
43
67
  - lib/tap/app.rb
44
68
  - lib/tap/app/api.rb
45
- - lib/tap/app/node.rb
46
69
  - lib/tap/app/queue.rb
47
70
  - lib/tap/app/stack.rb
48
71
  - lib/tap/app/state.rb
72
+ - lib/tap/declarations.rb
73
+ - lib/tap/declarations/context.rb
74
+ - lib/tap/declarations/description.rb
49
75
  - lib/tap/env.rb
76
+ - lib/tap/env/cache.rb
50
77
  - lib/tap/env/constant.rb
51
- - lib/tap/env/context.rb
52
- - lib/tap/env/gems.rb
53
- - lib/tap/env/manifest.rb
54
- - lib/tap/env/minimap.rb
78
+ - lib/tap/env/path.rb
55
79
  - lib/tap/env/string_ext.rb
56
- - lib/tap/intern.rb
57
80
  - lib/tap/join.rb
58
- - lib/tap/joins.rb
81
+ - lib/tap/joins/gate.rb
59
82
  - lib/tap/joins/switch.rb
60
83
  - lib/tap/joins/sync.rb
61
84
  - lib/tap/middleware.rb
62
85
  - lib/tap/middlewares/debugger.rb
63
86
  - lib/tap/parser.rb
64
- - lib/tap/prompt.rb
65
87
  - lib/tap/root.rb
66
- - lib/tap/root/utils.rb
67
- - lib/tap/root/versions.rb
88
+ - lib/tap/signal.rb
68
89
  - lib/tap/signals.rb
69
90
  - lib/tap/signals/class_methods.rb
91
+ - lib/tap/signals/configure.rb
70
92
  - lib/tap/signals/help.rb
93
+ - lib/tap/signals/load.rb
71
94
  - lib/tap/signals/module_methods.rb
72
- - lib/tap/signals/signal.rb
73
95
  - lib/tap/task.rb
74
96
  - lib/tap/tasks/dump.rb
75
97
  - lib/tap/tasks/load.rb
98
+ - lib/tap/tasks/list.rb
99
+ - lib/tap/tasks/prompt.rb
100
+ - lib/tap/tasks/singleton.rb
101
+ - lib/tap/tasks/signal.rb
102
+ - lib/tap/tasks/stream.rb
76
103
  - lib/tap/templater.rb
104
+ - lib/tap/utils.rb
77
105
  - lib/tap/version.rb
106
+ - lib/tap/workflow.rb
107
+ - tap.yml
78
108
  - README
79
109
  - MIT-LICENSE
80
110
  - History
81
111
  - doc/API
112
+ - doc/Workflow Syntax
113
+ - doc/Ruby to Ruby
82
114
  - doc/Examples/Command Line
83
- - doc/Examples/Workflow
115
+ - doc/Examples/Tapfile
116
+ - doc/Configuration
84
117
  has_rdoc: true
85
118
  homepage: http://tap.rubyforge.org
86
119
  licenses: []
@@ -99,18 +132,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
99
132
  requirements:
100
133
  - - ">="
101
134
  - !ruby/object:Gem::Version
135
+ segments:
136
+ - 0
102
137
  version: "0"
103
- version:
104
138
  required_rubygems_version: !ruby/object:Gem::Requirement
105
139
  requirements:
106
140
  - - ">="
107
141
  - !ruby/object:Gem::Version
142
+ segments:
143
+ - 0
108
144
  version: "0"
109
- version:
110
145
  requirements: []
111
146
 
112
147
  rubyforge_project: tap
113
- rubygems_version: 1.3.5
148
+ rubygems_version: 1.3.6
114
149
  signing_key:
115
150
  specification_version: 3
116
151
  summary: A configurable, distributable workflow framework.