coulis 0.1.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 +136 -0
  2. data/test/coulis_test.rb +165 -0
  3. metadata +63 -0
data/lib/coulis.rb ADDED
@@ -0,0 +1,136 @@
1
+ require "timeout"
2
+
3
+ class Coulis
4
+ class << self
5
+ attr_accessor :args, :_definitions, :_bin, :timeout
6
+
7
+ def exec(*args, &block)
8
+ self.new.exec *args, &block
9
+ end
10
+
11
+ def options(&block)
12
+ self.new(&block)
13
+ end
14
+
15
+ def bin(p)
16
+ @_bin = p.to_s
17
+ end
18
+
19
+ def _timeout(t)
20
+ @timeout = t
21
+ end
22
+
23
+ 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
+ if args.to_s.empty?
37
+ @args << [ definition || "#{"-" if m[0..0] != "-"}#{m}" ]
38
+ else
39
+ q = ""
40
+ q = "'" if args.to_s[0..0] != "'"
41
+ @args << [ definition || "#{"-" if m[0..0] != "-"}#{m}" , "#{q}#{args}#{q}" ]
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ attr_accessor :args
48
+
49
+ def initialize(&block)
50
+ self.class.instance_eval(&block) if block_given?
51
+ @args = self.class.args
52
+ self.class.args = []
53
+ self
54
+ end
55
+
56
+ def options(&block)
57
+ self.class.args = @args
58
+ self.class.new(&block)
59
+ end
60
+
61
+ def remove(*args)
62
+ new_args = []
63
+ args.each do |a|
64
+ @args.select {|b| b[0] == (self.class._definitions[a] || "-#{a}")}.each do |b|
65
+ @args.delete(b)
66
+ end
67
+ end
68
+ self.class.args = @args
69
+ self
70
+ end
71
+
72
+ def reset
73
+ @args = []
74
+ self.class.args = []
75
+ end
76
+
77
+ def build_args
78
+ return if @args.nil? or @args.empty?
79
+ @args.flatten.join(" ")
80
+ end
81
+
82
+ def command
83
+ "#{self.class._bin || self.class.to_s.downcase} #{build_args}".strip
84
+ end
85
+
86
+ def fire_command(&block)
87
+ puts command + " (timeout: #{self.class.timeout || -1}) + #{block_given?}" if $DEBUG
88
+ res = "" unless block_given?
89
+ IO.popen(command + " 3>&2 2>&1") do |pipe|
90
+ pipe.each("\r") do |line|
91
+ if block_given?
92
+ yield parse_output(line)
93
+ else
94
+ res << line
95
+ end
96
+ end
97
+ end
98
+ return (block_given? ? $? : parse_output(res))
99
+ end
100
+
101
+ def parse_output(output)
102
+ output
103
+ end
104
+
105
+ def method_missing(m, args=nil)
106
+ self.class.args = @args
107
+ self.class.method_missing(m, args)
108
+ @args = self.class.args
109
+ self
110
+ end
111
+
112
+ def inspect
113
+ "#<#{self.class.to_s} command=#{command} timeout=#{self.class.timeout || -1}>"
114
+ end
115
+
116
+ def exec(*args, &block)
117
+ if args.size > 0
118
+ i = 0
119
+ (args.size / 2).times do
120
+ self.class.send(args[i], args[i+1])
121
+ i+=2
122
+ end
123
+
124
+ @args = self.class.args
125
+ self.class.args = []
126
+ end
127
+
128
+ if self.class.timeout
129
+ Timeout::timeout(self.class.timeout) do
130
+ fire_command(&block)
131
+ end
132
+ else
133
+ fire_command(&block)
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,165 @@
1
+ require "test/unit"
2
+ require "coulis"
3
+
4
+ class Ls < Coulis
5
+ adef :all, "-a"
6
+ adef :human, "-h"
7
+
8
+ adef :full do
9
+ all; human
10
+ end
11
+ end
12
+
13
+ class Ping < Coulis
14
+ bin `whereis ping`.strip
15
+ adef :count, "-c"
16
+ end
17
+
18
+ class NSLookup < Coulis
19
+ def parse_output(output)
20
+ output.split("\n").
21
+ map{|x| x.match(/Address: ([0-9\.]+)/)[1] rescue nil}.
22
+ compact
23
+ end
24
+ end
25
+
26
+ class SimpleCliTest < Test::Unit::TestCase
27
+ def teardown
28
+ Ls.new.reset
29
+ Ping.new.reset
30
+ end
31
+
32
+ def test_default_bin
33
+ assert_equal Ls.new.command, "ls"
34
+ end
35
+
36
+ def test_defined_bin
37
+ assert_equal Ping.new.command, `whereis ping`.strip
38
+ assert_equal Ping.new.command, Ping._bin
39
+ end
40
+
41
+ def test_adef
42
+ assert_equal Ls._definitions[:all], "-a"
43
+ assert_equal Ls._definitions[:human], "-h"
44
+ end
45
+
46
+ def test_adef_with_block
47
+ assert_instance_of Proc, Ls._definitions[:full]
48
+ assert_equal Ls._definitions[:full].call, ["-a", "-h"]
49
+ end
50
+
51
+ def test_argument_added
52
+ ls = Ls.options { all }
53
+ assert true, ls.args[0] == "-a"
54
+ end
55
+
56
+ def test_all_arguments_from_adef_added
57
+ ls = Ls.options { full }
58
+ assert_equal ls.args.size, 2
59
+ end
60
+
61
+ def test_not_defined_argument
62
+ ls = Ls.options { s }
63
+ assert_equal ls.args.size, 1
64
+ assert_equal ls.args.to_s, "-s"
65
+ end
66
+
67
+ def test_command
68
+ assert_equal Ls.options { full; s }.command, "ls -a -h -s"
69
+ end
70
+
71
+ def test_add_options
72
+ ls = Ls.options { a }
73
+ assert_equal ls.args.flatten.size, 1
74
+ ls.options { l; h }
75
+ assert_equal ls.args.flatten.size, 3
76
+
77
+ assert_equal ls.command, "ls -a -l -h"
78
+ end
79
+
80
+ def test_add_option
81
+ ls = Ls.new
82
+ ls.all
83
+ assert_equal ls.args.flatten.size, 1
84
+ assert_equal ls.command, "ls -a"
85
+
86
+ ls.l
87
+ assert_equal ls.args.flatten.size, 2
88
+ assert_equal ls.command, "ls -a -l"
89
+ end
90
+
91
+ def test_add_option_with_args
92
+ ping = Ping.options {
93
+ @args << ["-c", 2] << ["google.com"]
94
+ }
95
+
96
+ assert_equal ping.command, "#{Ping._bin} -c 2 google.com"
97
+ end
98
+
99
+ def test_remove_options
100
+ ls = Ls.options { a; l; h }
101
+ ls.remove :a, :h
102
+ assert_equal ls.command, "ls -l"
103
+
104
+ ls.reset
105
+ ls.all
106
+ ls.remove :all
107
+ assert_equal ls.command, "ls"
108
+ end
109
+
110
+ def test_reset
111
+ ls = Ls.options { a; l; h }
112
+ assert_equal ls.command, "ls -a -l -h"
113
+ ls.reset
114
+ assert_equal ls.command, "ls"
115
+ end
116
+
117
+ def test_exec
118
+ ls = Ls.options { full }.exec
119
+
120
+ assert_instance_of String, ls
121
+ assert true, ls.size > 0
122
+ end
123
+
124
+ def test_exec_with_block
125
+ ls = Ls.options { full }
126
+ process = ls.exec do |out|
127
+ assert_instance_of String, out
128
+ assert true, out.size > 0
129
+ end
130
+
131
+ assert_instance_of Process::Status, process
132
+ assert_equal process.exitstatus, 0
133
+ end
134
+
135
+ def test_timeout
136
+ assert_raise Timeout::Error do
137
+ Ping.options {
138
+ @args << ["google.com"]
139
+ _timeout 2
140
+ }.exec
141
+ end
142
+ assert_equal Ping.timeout, 2
143
+ end
144
+
145
+ def test_stdout
146
+ res = ""
147
+ Ping.options {
148
+ count 2
149
+ @args << ["google.com"]
150
+ }.exec do |out|
151
+ res << out
152
+ end
153
+
154
+ assert true, res.size > 0
155
+ end
156
+
157
+ def test_parse_output
158
+ NSLookup.options {
159
+ @args = ["google.com"]
160
+ }.exec do |ips|
161
+ assert_instance_of Array, ips
162
+ assert true, ips.size > 1
163
+ end
164
+ end
165
+ end
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: coulis
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Bruno Celeste
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-07-21 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Simple but powerful CLI Wrapper
22
+ email: bruno.celeste@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - lib/coulis.rb
31
+ - test/coulis_test.rb
32
+ has_rdoc: true
33
+ homepage: http://github.com/sadikzzz/coulis
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options: []
38
+
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ requirements: []
56
+
57
+ rubyforge_project:
58
+ rubygems_version: 1.3.6
59
+ signing_key:
60
+ specification_version: 3
61
+ summary: A simple CLI Wrapper
62
+ test_files: []
63
+