coulis 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/coulis.rb +116 -42
  2. data/test/coulis_test.rb +106 -37
  3. metadata +10 -7
data/lib/coulis.rb CHANGED
@@ -2,7 +2,7 @@ require "timeout"
2
2
 
3
3
  class Coulis
4
4
  class << self
5
- attr_accessor :args, :_definitions, :_bin, :timeout
5
+ attr_accessor :_definitions, :bin, :timeout, :no_double_dash
6
6
 
7
7
  def exec(*args, &block)
8
8
  self.new.exec *args, &block
@@ -12,69 +12,49 @@ class Coulis
12
12
  self.new(&block)
13
13
  end
14
14
 
15
- def bin(p)
16
- @_bin = p.to_s
15
+ def _bin(p)
16
+ @bin = p.to_s
17
17
  end
18
18
 
19
19
  def _timeout(t)
20
20
  @timeout = t
21
21
  end
22
22
 
23
+ def _no_double_dash
24
+ @no_double_dash = true
25
+ end
26
+
23
27
  def adef(name, option=nil, &block)
24
- (@_definitions||={})[name.to_sym] = (option || Proc.new { self.instance_eval(&block).flatten })
25
- end
26
-
27
- def method_missing(m, args=nil)
28
- m = m.to_s.gsub("=", "")
29
- @args ||= []
30
- definition = @_definitions[m.to_sym] rescue nil
31
-
32
- #puts "m: #{m}, def: #{definition.inspect} | args:#{args}"
33
- if definition.is_a?(Proc)
34
- definition.call
35
- else
36
- arg_name = "#{"-" if m[0..0] != "-"}#{m}"
37
- arg_name = "-" + arg_name.gsub("_", "-") if arg_name.size > 2
38
-
39
- if args.to_s.empty?
40
- @args << [ definition || arg_name ]
41
- else
42
- q = ""
43
- q = "'" if args.to_s[0..0] != "'"
44
- @args << [ definition || arg_name , "#{q}#{args}#{q}" ]
45
- end
46
- end
28
+ (@_definitions||={})[name.to_sym] = (option || block )
47
29
  end
48
30
  end
49
31
 
50
32
  attr_accessor :args
51
33
 
52
34
  def initialize(&block)
53
- self.class.instance_eval(&block) if block_given?
54
- @args = self.class.args
55
- self.class.args = []
35
+ @args ||= []
36
+ self.instance_eval(&block) if block_given?
56
37
  self
57
38
  end
58
39
 
59
40
  def options(&block)
60
- self.class.args = @args
61
- self.class.new(&block)
41
+ self.instance_eval(&block)
42
+ self
62
43
  end
63
44
 
64
45
  def remove(*args)
65
46
  new_args = []
47
+ defs = self.class._definitions || {}
66
48
  args.each do |a|
67
- @args.select {|b| b[0] == (self.class._definitions[a] || "-#{a}")}.each do |b|
49
+ @args.select {|b| b[0] == (defs[a] || argumentize(a))}.each do |b|
68
50
  @args.delete(b)
69
51
  end
70
52
  end
71
- self.class.args = @args
72
53
  self
73
54
  end
74
55
 
75
56
  def reset
76
57
  @args = []
77
- self.class.args = []
78
58
  end
79
59
 
80
60
  def build_args
@@ -82,22 +62,52 @@ class Coulis
82
62
  @args.flatten.join(" ")
83
63
  end
84
64
 
65
+ def argumentize(argname)
66
+ argname = "#{"-" if argname.to_s[0..0] != "-"}#{argname}"
67
+ if !self.class.no_double_dash && argname.size > 2
68
+ argname = "-" + argname.gsub("_", "-")
69
+ end
70
+ argname
71
+ end
72
+
73
+ def value_by_arg(argname)
74
+ definition = self.class._definitions[argname.to_sym] || argumentize(argname)
75
+
76
+ result = @args.find{|a| a[0].to_s == definition.to_s}
77
+ return if result.nil?
78
+
79
+ value = result[1]
80
+ return nil if value.nil?
81
+
82
+ if value[0..0] == "'" && value[-1..-1]
83
+ return value[1..-2]
84
+ else
85
+ return value
86
+ end
87
+ end
88
+
85
89
  def command
86
- "#{self.class._bin || self.class.to_s.downcase} #{build_args}".strip
90
+ "#{self.class.bin || self.class.to_s.downcase} #{build_args}".strip
87
91
  end
88
92
 
89
93
  def fire_command(&block)
90
94
  puts command + " (timeout: #{self.class.timeout || -1}) + #{block_given?}" if $DEBUG
91
- res = "" unless block_given?
95
+ res = ""
92
96
  IO.popen(command + " 3>&2 2>&1") do |pipe|
93
97
  pipe.each("\r") do |line|
98
+ res << line
94
99
  if block_given?
95
100
  yield parse_output(line)
96
- else
97
- res << line
98
101
  end
99
102
  end
100
103
  end
104
+ if $?.exitstatus != 0
105
+ @on_error_block.call(res) if @on_error_block.is_a?(Proc)
106
+ after_error($?, res)
107
+ else
108
+ @on_success_block.call(res) if @on_success_block.is_a?(Proc)
109
+ after_success($?, res)
110
+ end
101
111
  return (block_given? ? $? : parse_output(res))
102
112
  end
103
113
 
@@ -105,10 +115,74 @@ class Coulis
105
115
  output
106
116
  end
107
117
 
108
- def method_missing(m, args=nil)
109
- self.class.args = @args
110
- self.class.method_missing(m, args)
111
- @args = self.class.args
118
+ def on_error(&block)
119
+ @on_error_block = block
120
+ self
121
+ end
122
+
123
+ def on_success(&block)
124
+ @on_success_block = block
125
+ self
126
+ end
127
+
128
+ def after_success(proc, res); end
129
+ def after_error(proc, res); end
130
+
131
+ def _timeout(value)
132
+ self.class.timeout = value
133
+ end
134
+
135
+ def _bin(path)
136
+ self.class.bin = path
137
+ end
138
+
139
+ def method_missing(m, *args)
140
+ m = m.to_s.gsub("=", "")
141
+ @args ||= []
142
+ definition = self.class._definitions[m.to_sym] rescue nil
143
+ #puts "m: #{m}, args: #{args.inspect}, definition: #{definition.inspect}"
144
+ arg_name = argumentize(m)
145
+
146
+ if args.to_s.empty?
147
+ insert_arg [ definition || arg_name ]
148
+ return self
149
+ end
150
+
151
+ q = ""
152
+ q = "'" if args[0].to_s[0..0] != "'"
153
+ full_arg = [ definition || arg_name , "#{q}#{args[0]}#{q}" ]
154
+
155
+ insert_arg(full_arg, args[1])
156
+ # delete doublon
157
+ if args[1] && args[1].has_key?(:uniq)
158
+ uniq_arg(definition || arg_name)
159
+ end
160
+ self
161
+ end
162
+
163
+ def uniq_arg(arg)
164
+ if found = @args.find{|a| a[0] == arg}
165
+ @args.delete found
166
+ end
167
+ self
168
+ end
169
+
170
+ def insert_arg(arg, opts=nil)
171
+ if !opts
172
+ @args << arg
173
+ return self
174
+ end
175
+
176
+ if arg_to_find = opts[:before] || opts[:after]
177
+ found = @args.find{|a|
178
+ a[0] == self.class._definitions[arg_to_find.to_sym] || arg_to_find
179
+ }
180
+ if found && index = @args.index(found)
181
+ @args.insert(index+1, arg)
182
+ end
183
+ else
184
+ @args << arg
185
+ end
112
186
  self
113
187
  end
114
188
 
data/test/coulis_test.rb CHANGED
@@ -4,14 +4,16 @@ require "coulis"
4
4
  class Ls < Coulis
5
5
  adef :all, "-a"
6
6
  adef :human, "-h"
7
+ adef :full, "-a -h"
8
+ end
7
9
 
8
- adef :full do
9
- all; human
10
- end
10
+ class FFMpeg < Coulis
11
+ _no_double_dash
12
+ adef :input, "-i"
11
13
  end
12
14
 
13
15
  class Ping < Coulis
14
- bin `whereis ping`.strip
16
+ _bin `whereis ping`.strip
15
17
  adef :count, "-c"
16
18
  end
17
19
 
@@ -25,8 +27,12 @@ end
25
27
 
26
28
  class SimpleCliTest < Test::Unit::TestCase
27
29
  def teardown
28
- Ls.new.reset
29
- Ping.new.reset
30
+ #Ls.new.reset
31
+ #Ping.new.reset
32
+ end
33
+
34
+ def test_shit
35
+ #p Ls.options { full }
30
36
  end
31
37
 
32
38
  def test_default_bin
@@ -35,7 +41,7 @@ class SimpleCliTest < Test::Unit::TestCase
35
41
 
36
42
  def test_defined_bin
37
43
  assert_equal Ping.new.command, `whereis ping`.strip
38
- assert_equal Ping.new.command, Ping._bin
44
+ assert_equal Ping.new.command, Ping.bin
39
45
  end
40
46
 
41
47
  def test_adef
@@ -43,9 +49,8 @@ class SimpleCliTest < Test::Unit::TestCase
43
49
  assert_equal Ls._definitions[:human], "-h"
44
50
  end
45
51
 
46
- def test_adef_with_block
47
- assert_instance_of Proc, Ls._definitions[:full]
48
- assert_equal Ls._definitions[:full].call, ["-a", "-h"]
52
+ def test_adef_with_multiple_args
53
+ assert_equal Ls._definitions[:full], "-a -h"
49
54
  end
50
55
 
51
56
  def test_argument_added
@@ -53,51 +58,58 @@ class SimpleCliTest < Test::Unit::TestCase
53
58
  assert true, ls.args[0] == "-a"
54
59
  end
55
60
 
56
- def test_all_arguments_from_adef_added
57
- ls = Ls.options { full }
58
- assert_equal ls.args.size, 2
59
- end
60
-
61
61
  def test_not_defined_short_argument
62
- ls = Ls.options { s }
63
- assert_equal ls.args.size, 1
64
- assert_equal ls.args.to_s, "-s"
62
+ ls = Ls.options { g }
63
+ assert_equal 1, ls.args.size
64
+ assert_equal "-g", ls.args.to_s
65
65
  end
66
66
 
67
67
  def test_not_defined_long_argument
68
68
  ls = Ls.options { color }
69
- assert_equal ls.args.size, 1
70
- assert_equal ls.args.to_s, "--color"
69
+ assert_equal 1, ls.args.size
70
+ assert_equal "--color", ls.args.to_s
71
71
  end
72
72
 
73
73
  def test_not_defined_long_argument_with_underscore
74
74
  ls = Ls.options { color_test }
75
- assert_equal ls.args.size, 1
76
- assert_equal ls.args.to_s, "--color-test"
75
+ assert_equal 1, ls.args.size
76
+ assert_equal "--color-test", ls.args.to_s
77
+ end
78
+
79
+ def test_no_double_dash_option
80
+ ffmpeg = FFMpeg.options { vcodec "libx264" }
81
+ assert_equal "ffmpeg -vcodec 'libx264'", ffmpeg.command
82
+ end
83
+
84
+ def test_remove_args_if_not_defined
85
+ ffmpeg = FFMpeg.options { vcodec "libx264" }
86
+ assert_equal 1, ffmpeg.args.size
87
+ ffmpeg.remove :vcodec
88
+ assert_equal 0, ffmpeg.args.size
77
89
  end
78
90
 
79
91
  def test_command
80
- assert_equal Ls.options { full; s }.command, "ls -a -h -s"
92
+ assert_equal "ls -a -h -g", Ls.options { full; g }.command
81
93
  end
82
94
 
83
95
  def test_add_options
84
96
  ls = Ls.options { a }
85
- assert_equal ls.args.flatten.size, 1
97
+ assert_equal 1, ls.args.flatten.size
86
98
  ls.options { l; h }
87
- assert_equal ls.args.flatten.size, 3
99
+ assert_equal 3, ls.args.flatten.size
88
100
 
89
- assert_equal ls.command, "ls -a -l -h"
101
+ assert_equal "ls -a -l -h", ls.command
90
102
  end
91
103
 
92
104
  def test_add_option
93
105
  ls = Ls.new
94
106
  ls.all
95
- assert_equal ls.args.flatten.size, 1
96
- assert_equal ls.command, "ls -a"
107
+ assert_equal 1, ls.args.flatten.size
108
+ assert_equal "ls -a", ls.command
97
109
 
98
110
  ls.l
99
- assert_equal ls.args.flatten.size, 2
100
- assert_equal ls.command, "ls -a -l"
111
+ assert_equal 2, ls.args.flatten.size
112
+ assert_equal "ls -a -l", ls.command
101
113
  end
102
114
 
103
115
  def test_add_option_with_args
@@ -105,25 +117,25 @@ class SimpleCliTest < Test::Unit::TestCase
105
117
  @args << ["-c", 2] << ["google.com"]
106
118
  }
107
119
 
108
- assert_equal ping.command, "#{Ping._bin} -c 2 google.com"
120
+ assert_equal ping.command, "#{Ping.bin} -c 2 google.com"
109
121
  end
110
122
 
111
123
  def test_remove_options
112
124
  ls = Ls.options { a; l; h }
113
125
  ls.remove :a, :h
114
- assert_equal ls.command, "ls -l"
126
+ assert_equal "ls -l", ls.command
115
127
 
116
128
  ls.reset
117
129
  ls.all
118
130
  ls.remove :all
119
- assert_equal ls.command, "ls"
131
+ assert_equal "ls", ls.command
120
132
  end
121
133
 
122
134
  def test_reset
123
135
  ls = Ls.options { a; l; h }
124
- assert_equal ls.command, "ls -a -l -h"
136
+ assert_equal "ls -a -l -h", ls.command
125
137
  ls.reset
126
- assert_equal ls.command, "ls"
138
+ assert_equal "ls", ls.command
127
139
  end
128
140
 
129
141
  def test_exec
@@ -141,7 +153,7 @@ class SimpleCliTest < Test::Unit::TestCase
141
153
  end
142
154
 
143
155
  assert_instance_of Process::Status, process
144
- assert_equal process.exitstatus, 0
156
+ assert_equal 0, process.exitstatus
145
157
  end
146
158
 
147
159
  def test_timeout
@@ -151,7 +163,7 @@ class SimpleCliTest < Test::Unit::TestCase
151
163
  _timeout 2
152
164
  }.exec
153
165
  end
154
- assert_equal Ping.timeout, 2
166
+ assert_equal 2, Ping.timeout
155
167
  end
156
168
 
157
169
  def test_stdout
@@ -174,4 +186,61 @@ class SimpleCliTest < Test::Unit::TestCase
174
186
  assert true, ips.size > 1
175
187
  end
176
188
  end
189
+
190
+ def test_success_event
191
+ process = Ls.options {
192
+ all
193
+ }.on_success {|out|
194
+ assert_instance_of Process::Status, $?
195
+ assert_equal 0, $?.exitstatus
196
+ assert_instance_of String, out
197
+ }.exec {|out|
198
+ assert_instance_of String, out
199
+ }
200
+ end
201
+
202
+ def test_error_event
203
+ process = Ls.options {
204
+ @args = ["/not/a/path"]
205
+ }.on_error {|out|
206
+ assert_instance_of Process::Status, $?
207
+ assert_equal 1, $?.exitstatus
208
+ assert_instance_of String, out
209
+ }.exec {|out|
210
+ assert_instance_of String, out
211
+ }
212
+ end
213
+
214
+ def test_getting_value_by_arg
215
+ ffmpeg = FFMpeg.options { input "video.mp4"; vcodec "libx264"}
216
+ assert_equal "video.mp4", ffmpeg.value_by_arg(:input)
217
+ assert_equal "libx264", ffmpeg.value_by_arg(:vcodec)
218
+ end
219
+
220
+ def test_adding_arg_before_another
221
+ ffmpeg = FFMpeg.options {
222
+ input "video.mp4"
223
+ y "out.avi"
224
+ vcodec "libx264", :before => "-y"
225
+ }
226
+ assert_equal "ffmpeg -i 'video.mp4' -vcodec 'libx264' -y 'out.avi'", ffmpeg.command
227
+ end
228
+
229
+ def test_adding_arg_after_another
230
+ ffmpeg = FFMpeg.options {
231
+ input "video.mp4"
232
+ y "out.avi"
233
+ }
234
+ ffmpeg.vcodec "libx264", :after => :input
235
+ assert_equal "ffmpeg -i 'video.mp4' -vcodec 'libx264' -y 'out.avi'", ffmpeg.command
236
+ end
237
+
238
+ def test_adding_uniq_arg
239
+ ffmpeg = FFMpeg.options {
240
+ input "video.mp4"
241
+ y "out.avi"
242
+ }
243
+ ffmpeg.input "video2.mp4", :before => "-y", :uniq => true
244
+ assert_equal "ffmpeg -i 'video2.mp4' -y 'out.avi'", ffmpeg.command
245
+ end
177
246
  end
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coulis
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
4
+ hash: 23
5
+ prerelease:
5
6
  segments:
6
7
  - 0
7
- - 1
8
8
  - 2
9
- version: 0.1.2
9
+ - 0
10
+ version: 0.2.0
10
11
  platform: ruby
11
12
  authors:
12
13
  - Bruno Celeste
@@ -14,8 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2011-07-23 00:00:00 +02:00
18
- default_executable:
18
+ date: 2012-07-03 00:00:00 Z
19
19
  dependencies: []
20
20
 
21
21
  description: Simple but powerful CLI Wrapper
@@ -29,7 +29,6 @@ extra_rdoc_files: []
29
29
  files:
30
30
  - lib/coulis.rb
31
31
  - test/coulis_test.rb
32
- has_rdoc: true
33
32
  homepage: http://github.com/sadikzzz/coulis
34
33
  licenses: []
35
34
 
@@ -39,23 +38,27 @@ rdoc_options: []
39
38
  require_paths:
40
39
  - lib
41
40
  required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
42
  requirements:
43
43
  - - ">="
44
44
  - !ruby/object:Gem::Version
45
+ hash: 3
45
46
  segments:
46
47
  - 0
47
48
  version: "0"
48
49
  required_rubygems_version: !ruby/object:Gem::Requirement
50
+ none: false
49
51
  requirements:
50
52
  - - ">="
51
53
  - !ruby/object:Gem::Version
54
+ hash: 3
52
55
  segments:
53
56
  - 0
54
57
  version: "0"
55
58
  requirements: []
56
59
 
57
60
  rubyforge_project:
58
- rubygems_version: 1.3.6
61
+ rubygems_version: 1.8.24
59
62
  signing_key:
60
63
  specification_version: 3
61
64
  summary: A simple CLI Wrapper