cmds 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 746aa0ec8697ab254e151c8000620c7a3a6d8c52
4
- data.tar.gz: d15e1589321da1a22ad00d98cb12875d71a0ea7b
3
+ metadata.gz: 327a49d0895e5e91d1d35c9ab352357a4a577f65
4
+ data.tar.gz: f2f7bd60a0b9bcdfca5a7e50a28ac386f329d33a
5
5
  SHA512:
6
- metadata.gz: 186e86b834c8d38aa58b624c394acc850848fff6faac92ff10ecd3336992beff7a6b9d3a139baaec9148b12e1fe036c04a29bf954dde6c27a14309cf69304f98
7
- data.tar.gz: de1c715943e12a45f003e5e9a4b0c9b63f8443c8c42a64a35d983f6d742404d82b28eddc06ad238d1777e3aaf20bb1b95ccc4871abfce1090d3b52c822e7846b
6
+ metadata.gz: c22d98773434a8c16df0420d599222e00df2f5fcca68e448f889f16671d35db3ab441faa8d6194419c690f435b60e28b1992cc2cbddb0614c79f26fa378e5033
7
+ data.tar.gz: ca4371971382c85c6438bafac00c40f637a9e7dbeb2e232838ea9ae2e11ffdc7de5f6989ccd76560f2d09cac452d7da5438e291a29b1baa24dc64e93e8abbacb
data/Rakefile CHANGED
@@ -1 +1,153 @@
1
+ require 'thread'
2
+ require 'pastel'
3
+ require 'json'
4
+ require 'pp'
5
+ require 'tempfile'
6
+
1
7
  require "bundler/gem_tasks"
8
+
9
+ Bundler.require
10
+
11
+ def configure_logger
12
+ logger = Logger.new $stderr
13
+
14
+ logger.level = case ENV['log']
15
+ when 'debug'
16
+ Logger::DEBUG
17
+ when 'info'
18
+ Logger::INFO
19
+ when 'warn'
20
+ Logger::WARN
21
+ when 'error'
22
+ Logger::ERROR
23
+ else
24
+ Logger::INFO
25
+ end
26
+
27
+ logger.formatter = proc do |severity, datetime, progname, msg|
28
+ formatted = if Thread.current[:name]
29
+ "[rake #{ severity } - #{ Thread.current[:name ] }] #{msg}\n"
30
+ else
31
+ "[rake #{ severity }] #{msg}\n"
32
+ end
33
+
34
+ if severity == 'DEBUG'
35
+ formatted = Pastel.new.cyan(formatted)
36
+ end
37
+
38
+ formatted
39
+ end
40
+ logger
41
+ end
42
+
43
+ def log
44
+ $logger ||= configure_logger
45
+ end
46
+
47
+ namespace :debug do
48
+ desc "turn debug logging on"
49
+ task :conf do
50
+ ENV['log'] ||= 'debug'
51
+ Cmds.enable_debug
52
+ end
53
+
54
+ task :proxy => :conf do
55
+ Cmds.new("./test/questions.rb").proxy
56
+ end
57
+
58
+ namespace :capture do
59
+ desc "capture with io-like input with debugging enabled"
60
+ task :io_input => :conf do
61
+ File.open "./test/lines.txt" do |f|
62
+ Cmds.new("./test/echo_cmd.rb", input: f).capture
63
+ end
64
+ end
65
+ end # ns capture
66
+
67
+ namespace :stream do
68
+ input = NRSER.dedent <<-BLOCK
69
+ one
70
+ two
71
+ three
72
+ BLOCK
73
+
74
+ desc "output to blocks"
75
+ task :blocks => :conf do
76
+ Cmds.stream "ls" do |io|
77
+ io.on_out do |line|
78
+ puts "line: #{ line.inspect }"
79
+ end
80
+ end
81
+ end
82
+
83
+ desc "use a file as output"
84
+ task :file_out => :conf do
85
+ f = Tempfile.new "blah"
86
+ Cmds.stream "echo here" do |io|
87
+ io.out = f
88
+ end
89
+
90
+ f.rewind
91
+ puts f.read
92
+ f.close
93
+ f.unlink
94
+ end
95
+
96
+ desc "input block value"
97
+ task :value => :conf do
98
+ Cmds.stream "wc -l" do
99
+ input
100
+ end
101
+ end
102
+
103
+ desc "input block hanlder"
104
+ task :handler => :conf do
105
+ Cmds.stream "wc -l" do |io|
106
+ io.on_in do
107
+ end
108
+ end
109
+ end
110
+
111
+ desc "input io"
112
+ task :io => :conf do
113
+ File.open "./test/lines.txt" do |f|
114
+ Cmds.stream("wc -l") { f }
115
+ end
116
+ end
117
+
118
+ # this was a vauge idea that doesn't yet work, and may never
119
+ # need a better understanding probably, so gonna punt for now
120
+ desc "play with questions"
121
+ task :questions => :conf do
122
+ q = nil
123
+ a = nil
124
+
125
+ as = {
126
+ "what is your name?" => 'nrser',
127
+ "what is your quest?" => 'make this shit work somehow',
128
+ "what is you favorite color?" => 'blue',
129
+ }
130
+
131
+ Cmds.stream "./test/questions.rb" do |io|
132
+ io.on_out do |line|
133
+ puts "on_out called"
134
+ q = line
135
+ puts "questions asked: #{ q }"
136
+ a = as[q]
137
+ raise "unknown question: #{ q }" unless a
138
+ puts "setting answer to #{ a }..."
139
+ end
140
+
141
+ io.on_in do |f|
142
+ puts "on_in called"
143
+ if a
144
+ puts "responding with #{ a }."
145
+ f.write a
146
+ else
147
+ puts "no response ready."
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end # namespace stream
153
+ end # namespace debug
data/ansible/dev.yml CHANGED
@@ -10,6 +10,11 @@
10
10
  version: master
11
11
  dir_name: rails
12
12
 
13
+ - owner: ruby
14
+ name: ruby
15
+ version: v2_2_2
16
+ dir_name: ruby-v2_2_2
17
+
13
18
  tasks:
14
19
 
15
20
  - name: install gems
data/cmds.gemspec CHANGED
@@ -24,4 +24,5 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "bundler", "~> 1.5"
25
25
  spec.add_development_dependency "rake"
26
26
  spec.add_development_dependency "rspec"
27
+ spec.add_development_dependency "pastel"
27
28
  end
@@ -0,0 +1,47 @@
1
+ class Cmds
2
+ # invokes the command and returns a Result with the captured outputs
3
+ def capture *subs, &input_block
4
+ Cmds.debug "entering Cmds#capture",
5
+ subs: subs,
6
+ input_block: input_block
7
+
8
+ # merge any stored args and kwds and replace input if provided
9
+ options = merge_options subs, input_block
10
+ Cmds.debug "merged options:",
11
+ options: options
12
+
13
+ # build the command string
14
+ cmd = Cmds.sub @template, options[:args], options[:kwds]
15
+ Cmds.debug "built command string: #{ cmd.inspect }"
16
+
17
+ out = ''
18
+ err = ''
19
+
20
+ Cmds.debug "calling Cmds#really_stream..."
21
+ status = really_stream cmd, options do |io|
22
+ # send the input to stream, which sends it to spawn
23
+ io.in = options[:input]
24
+
25
+ # and concat the output lines as they come in
26
+ io.on_out do |line|
27
+ out += line
28
+ end
29
+
30
+ io.on_err do |line|
31
+ err += line
32
+ end
33
+ end
34
+ Cmds.debug "Cmds#really_stream completed",
35
+ status: status
36
+
37
+ # build a Result
38
+ # result = Cmds::Result.new cmd, status, out_reader.value, err_reader.value
39
+ result = Cmds::Result.new cmd, status, out, err
40
+
41
+ # tell the Result to assert if the Cmds has been told to, which will
42
+ # raise a SystemCallError with the exit status if it was non-zero
43
+ result.assert if @assert
44
+
45
+ return result
46
+ end # #capture
47
+ end
data/lib/cmds/debug.rb ADDED
@@ -0,0 +1,101 @@
1
+ require 'logger'
2
+
3
+ # debug logging stuff
4
+ class Cmds
5
+
6
+ module Debug
7
+ # constants
8
+
9
+ # change the color of debug output by thread name (if present)
10
+ THREAD_COLORS = {
11
+ 'INPUT' => :cyan,
12
+ 'OUTPUT' => :green,
13
+ 'ERROR' => :red,
14
+ }
15
+ # available Pastel styles:
16
+ #
17
+ # clear, reset, bold, dark, dim, italic, underline, underscore, inverse, hidden, strikethrough,
18
+ # black, red, green, yellow, blue, magenta, cyan, white,
19
+ # on_black, on_red, on_green, on_yellow, on_blue, on_magenta, on_cyan, on_white,
20
+ # bright_black, bright_red, bright_green, bright_yellow, bright_blue, bright_magenta, bright_cyan, bright_white,
21
+ # on_bright_black, on_bright_red, on_bright_green, on_bright_yellow, on_bright_blue, on_bright_magenta, on_bright_cyan, on_bright_white
22
+ #
23
+
24
+ # class variables
25
+ @@on = false
26
+ @@logger = nil
27
+
28
+ # class methods
29
+ # =============
30
+
31
+ # get the Logger instance. may be `nil`.
32
+ def self.logger
33
+ @@logger
34
+ end
35
+
36
+ # test if the logger is configured.
37
+ def self.configured?
38
+ !! @@logger
39
+ end
40
+
41
+ # configure the Logger with optional destination
42
+ def self.configure dest = $stdout
43
+ require 'pastel'
44
+ @@pastel = Pastel.new
45
+
46
+ @@logger = Logger.new dest
47
+ @@logger.level = Logger::DEBUG
48
+ @@logger.formatter = proc do |severity, datetime, progname, msg|
49
+ if Thread.current[:name]
50
+ msg = "[Cmds #{ severity } - #{ Thread.current[:name ] }] #{msg}\n"
51
+
52
+ if color = THREAD_COLORS[Thread.current[:name]]
53
+ msg = @@pastel.method(color).call msg
54
+ end
55
+
56
+ msg
57
+ else
58
+ "[Cmds #{ severity }] #{msg}\n"
59
+ end
60
+ end
61
+ end
62
+
63
+ # turn debug logging on. if you provide a block it will turn debug logging
64
+ # on for that block and off at the end.
65
+ def self.on &block
66
+ configure unless configured?
67
+ @@on = true
68
+ if block
69
+ yield
70
+ off
71
+ end
72
+ end
73
+
74
+ # turn debug logging off.
75
+ def self.off
76
+ @@on = false
77
+ end
78
+
79
+ # test if debug logging is on.
80
+ def self.on?
81
+ @@on
82
+ end
83
+
84
+ # format a debug message with optional key / values to print
85
+ def self.format msg, values = {}
86
+ if values.empty?
87
+ msg
88
+ else
89
+ msg + "\n" + values.map {|k, v| " #{ k }: #{ v.inspect }" }.join("\n")
90
+ end
91
+ end
92
+
93
+ end # module Debug
94
+
95
+ # log a debug message along with an optional hash of values.
96
+ def self.debug msg, values = {}
97
+ # don't even bother unless debug logging is turned on
98
+ return unless Debug.on?
99
+ Debug.logger.debug Debug.format(msg, values)
100
+ end
101
+ end # class Cmds
@@ -0,0 +1,30 @@
1
+ class Cmds
2
+ class ERBContext < BasicObject
3
+ def initialize args, kwds
4
+ @args = args
5
+ @kwds = kwds
6
+ @arg_index = 0
7
+ end
8
+
9
+ def method_missing sym, *args, &block
10
+ if args.empty? && block.nil?
11
+ if sym.to_s[-1] == '?'
12
+ key = sym.to_s[0...-1].to_sym
13
+ @kwds[key]
14
+ else
15
+ @kwds.fetch sym
16
+ end
17
+ else
18
+ super
19
+ end
20
+ end
21
+
22
+ def get_binding
23
+ ::Kernel.send :binding
24
+ end
25
+
26
+ def arg
27
+ @args.fetch(@arg_index).tap {@arg_index += 1}
28
+ end
29
+ end # end ERBContext
30
+ end # class Cmds
@@ -0,0 +1,76 @@
1
+ class Cmds
2
+ class IOHandler
3
+ attr_accessor :in, :out, :err
4
+
5
+ def initialize
6
+ @queue = Queue.new
7
+ @in = nil
8
+ @out = $stdout
9
+ @err = $stderr
10
+ end
11
+
12
+ def on_out &block
13
+ @out = block
14
+ end
15
+
16
+ # called in seperate thread handling process IO
17
+ def thread_send_out line
18
+ @queue << [:out, line]
19
+ end
20
+
21
+ def on_err &block
22
+ @err = block
23
+ end
24
+
25
+ # called in seperate thread handling process IO
26
+ def thread_send_err line
27
+ @queue << [:err, line]
28
+ end
29
+
30
+ def thread_send_line sym, line
31
+ @queue << [sym, line]
32
+ end
33
+
34
+ def start
35
+ # if out is a proc, it's not done
36
+ out_done = ! @out.is_a?(Proc)
37
+ # same for err
38
+ err_done = ! @err.is_a?(Proc)
39
+
40
+ until out_done && err_done
41
+ key, line = @queue.pop
42
+
43
+ case key
44
+ when :out
45
+ if line.nil?
46
+ out_done = true
47
+ else
48
+ handle_line @out, line
49
+ end
50
+
51
+ when :err
52
+ if line.nil?
53
+ err_done = true
54
+ else
55
+ handle_line @err, line
56
+ end
57
+
58
+ else
59
+ raise "bad key: #{ key.inspect }"
60
+ end
61
+ end
62
+ end #start
63
+
64
+ private
65
+
66
+ def handle_line dest, line
67
+ if dest.is_a? Proc
68
+ dest.call line
69
+ else
70
+ dest.puts line
71
+ end
72
+ end
73
+
74
+ # end private
75
+ end # end IOHandler
76
+ end # class Cmds
data/lib/cmds/pipe.rb ADDED
@@ -0,0 +1,13 @@
1
+ class Cmds
2
+ # stupid little wrapper around IO.pipe that can have some extra info
3
+ # attached to it
4
+ class Pipe
5
+ attr_reader :name, :sym, :r, :w
6
+
7
+ def initialize name, sym
8
+ @name = name
9
+ @sym = sym
10
+ @r, @w = IO.pipe
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,34 @@
1
+ class Cmds
2
+ class Result
3
+ attr_reader :cmd, :status, :out, :err
4
+
5
+ def initialize cmd, status, out, err
6
+ @cmd = cmd
7
+ @status = status
8
+ @out = out
9
+ @err = err
10
+ end
11
+
12
+ def ok?
13
+ @status == 0
14
+ end
15
+
16
+ def error?
17
+ ! ok?
18
+ end
19
+
20
+ # raises an error if there was one
21
+ # returns the Result so that it can be chained
22
+ def assert
23
+ if error?
24
+ msg = NRSER.squish <<-BLOCK
25
+ command `#{ @cmd }` exited with status #{ @status }
26
+ and stderr #{ err.inspect }
27
+ BLOCK
28
+
29
+ raise SystemCallError.new msg, @status
30
+ end
31
+ self
32
+ end # raise_error
33
+ end
34
+ end # class Cmds
@@ -0,0 +1,11 @@
1
+ require 'erubis'
2
+
3
+ class Cmds
4
+ # extension of Erubis' EscapedEruby (which auto-escapes `<%= %>` and
5
+ # leaves `<%== %>` raw) that calls `Cmds.expand_sub` on the value
6
+ class ShellEruby < Erubis::EscapedEruby
7
+ def escaped_expr code
8
+ "::Cmds.expand_sub(#{code.strip})"
9
+ end
10
+ end
11
+ end # class Cmds