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.
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
+