coulis 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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