coulis 0.1.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.
- data/lib/coulis.rb +136 -0
- data/test/coulis_test.rb +165 -0
- 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
|
data/test/coulis_test.rb
ADDED
@@ -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
|
+
|