shell-proxy 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/README.md CHANGED
@@ -6,27 +6,65 @@ Totes leeb.
6
6
  Inputs:
7
7
 
8
8
  ```ruby
9
- require './shell_proxy'
9
+ require './lib/shell-proxy'
10
10
 
11
11
  ShellProxy.new.__main__ do
12
12
  cd "Somedir"
13
13
 
14
+ __function("butts_function") do
15
+ touch "butts"
16
+ end
17
+
14
18
  __subshell do
15
19
  __subshell do
16
20
  mkdir "borp"
17
21
  cd "borp"
18
22
  touch "thing"
19
23
  end
20
- touch "somefile"
24
+ %w[foo bar baz].each do |dir|
25
+ mkdir dir
26
+ touch "#{dir}/#{dir}"
27
+ end
28
+ touch("somefile")
21
29
  mkdir "foo/bar/thing", { :p => nil }
30
+ echo("foo") | wc({:c => nil})
22
31
  end
23
32
 
24
33
  __chdir "/tmp" do
25
34
  touch "rawr"
26
35
  end
27
36
 
37
+ __set("foo", bare("$RANDOM"))
38
+
39
+ some | thing | some | other | thing
40
+
41
+ __case(raw("$foo")) do |c|
42
+ c.when(10000) do
43
+ echo "holy shit, did not expect that"
44
+ end
45
+ c.when("*") do
46
+ echo "Welp, that was predictable"
47
+ end
48
+ end
49
+
50
+ __for(bare("foo bar baz"), "i") do
51
+ echo raw("$i")
52
+ end
53
+
28
54
  rm "foo", { :r => nil, :f => nil }
29
55
  mongod({ :config => "/usr/local/etc/mongod.conf" })
56
+
57
+ __if(raw("[[ $foo == 'foo' ]]")) do |c|
58
+ c.then do
59
+ echo "it was true"
60
+ end
61
+ c.elseif(raw("[[ bar == bar ]]")) do
62
+ echo "this is definitely true"
63
+ end
64
+ c.else do
65
+ echo "This wont be reached"
66
+ end
67
+ end
30
68
  end
31
69
  ```
32
70
 
@@ -34,19 +72,50 @@ outputs:
34
72
 
35
73
  ```bash
36
74
  cd 'Somedir'
75
+ function butts_function() {
76
+ touch 'butts'
77
+ }
37
78
  (
38
79
  (
39
80
  mkdir 'borp'
40
81
  cd 'borp'
41
82
  touch 'thing'
42
83
  )
84
+ mkdir 'foo'
85
+ touch 'foo/foo'
86
+ mkdir 'bar'
87
+ touch 'bar/bar'
88
+ mkdir 'baz'
89
+ touch 'baz/baz'
43
90
  touch 'somefile'
44
91
  mkdir '-p' 'foo/bar/thing'
92
+ echo 'foo' | wc '-c'
45
93
  )
46
94
  (
47
95
  cd '/tmp'
48
96
  touch 'rawr'
49
97
  )
98
+ foo=$RANDOM
99
+ some | thing | some | other | thing
100
+ case "$foo" in
101
+ 10000)
102
+ echo 'holy shit, did not expect that'
103
+ ;;
104
+ *)
105
+ echo 'Welp, that was predictable'
106
+ ;;
107
+ esac
108
+ for i in foo bar baz; do
109
+ echo "$i"
110
+ done
50
111
  rm '-r' '-f' 'foo'
51
112
  mongod '--config' '/usr/local/etc/mongod.conf'
113
+ if [[ $foo == 'foo' ]]
114
+ then
115
+ echo 'it was true'
116
+ else if [[ bar == bar ]]
117
+ echo 'this is definitely true'
118
+ else
119
+ echo 'This wont be reached'
120
+ fi
52
121
  ```
@@ -0,0 +1,203 @@
1
+ require_relative 'shell-proxy/escaping'
2
+ require_relative 'shell-proxy/case'
3
+ require_relative 'shell-proxy/for'
4
+ require_relative 'shell-proxy/if'
5
+
6
+ INDENT_PADDING=" "
7
+
8
+ class RawString < String
9
+ def quote
10
+ inspect
11
+ end
12
+ end
13
+
14
+ class BareString < String
15
+ end
16
+
17
+ def raw(s)
18
+ RawString.new(s)
19
+ end
20
+
21
+ def bare(s)
22
+ BareString.new(s)
23
+ end
24
+
25
+ class ShellProxy
26
+ include Escaping
27
+
28
+ def __main__(writer = nil, &block)
29
+ @cmd_buffer = CmdBuffer.new
30
+ instance_exec(&block)
31
+ @cmd_buffer.write(writer || __writer)
32
+ end
33
+
34
+ def __subshell(&block)
35
+ @cmd_buffer << "("
36
+ @cmd_buffer.indent
37
+ yield
38
+ @cmd_buffer.undent
39
+ @cmd_buffer << ")"
40
+ end
41
+
42
+ def __chdir(dir, &block)
43
+ __subshell do
44
+ cd(dir)
45
+ yield
46
+ end
47
+ end
48
+
49
+ def __case(value, &block)
50
+ CaseStub.new(__escapinate(value), &block).__handle(@cmd_buffer)
51
+ end
52
+
53
+ def __for(over, iter, &block)
54
+ ForStub.new(over, iter, &block).__handle(@cmd_buffer)
55
+ end
56
+
57
+ def __if(condition, &block)
58
+ IfStub.new(condition, &block).__handle(@cmd_buffer)
59
+ end
60
+
61
+ def __set(variable, value)
62
+ __eval("#{variable}=#{__escapinate(value)}")
63
+ end
64
+
65
+ def __return(val)
66
+ __eval("return #{__escapinate(val)}")
67
+ end
68
+
69
+ def __function(name, &block)
70
+ @cmd_buffer << "function #{name}() {"
71
+ @cmd_buffer.indent
72
+ yield
73
+ @cmd_buffer.undent
74
+ @cmd_buffer << "}"
75
+ end
76
+
77
+ def method_missing(sym, *args)
78
+ opts = case args[-1]
79
+ when Hash
80
+ args.pop
81
+ else
82
+ {}
83
+ end
84
+
85
+ stub = CmdStub.new(@cmd_buffer)
86
+
87
+ cmd = sym.to_s
88
+ cmd << " #{__process_opts(opts)}" unless opts.empty?
89
+ cmd << " #{__process_args(args)}" unless args.empty?
90
+ @cmd_buffer << cmd
91
+ stub
92
+ end
93
+
94
+ def __eval(str)
95
+ @cmd_buffer << str
96
+ end
97
+
98
+ def __emit(str)
99
+ __writer.flush
100
+ end
101
+
102
+ def __writer
103
+ @writer ||= ShellWriter.new($stdout)
104
+ end
105
+
106
+ def __process_args(args)
107
+ args.map do |v|
108
+ __escapinate(v)
109
+ end.join(" ")
110
+ end
111
+
112
+ def __process_opts(opts)
113
+ outputs = []
114
+ __process_and_escape(opts) do |value|
115
+ outputs << value
116
+ end
117
+ outputs.join(" ")
118
+ end
119
+
120
+ def __process_and_escape(opts)
121
+ opts.each do |k, v|
122
+ k = k.to_s
123
+ k = (k.length == 1 ? "-" : "--") + k
124
+ yield __escapinate(k)
125
+ yield __escapinate(v) unless v.nil?
126
+ end
127
+ end
128
+
129
+ end
130
+
131
+ class CmdStub
132
+ def initialize(buffer)
133
+ @buffer = buffer
134
+ end
135
+
136
+ def emit(data)
137
+ @emitter.call(data)
138
+ end
139
+
140
+ def |(other)
141
+ # Append a pipe to the second last command in the stack
142
+ last = @buffer.pop
143
+ @buffer << "#{@buffer.pop} | #{last.strip}"
144
+ self
145
+ end
146
+ end
147
+
148
+
149
+ class CmdBuffer
150
+ def initialize
151
+ @indent = 0
152
+ @buffer = []
153
+ end
154
+
155
+ def indent
156
+ @indent += 1
157
+ end
158
+
159
+ def undent
160
+ @indent -= 1
161
+ end
162
+
163
+ def << (other)
164
+ @buffer << "#{INDENT_PADDING * @indent}#{other}"
165
+ end
166
+
167
+ def pop
168
+ @buffer.pop
169
+ end
170
+
171
+ def write(buf)
172
+ @buffer.each do |l|
173
+ buf.puts l
174
+ end
175
+ buf.flush
176
+ end
177
+ end
178
+
179
+ class ShellWriter
180
+ def initialize(to)
181
+ case to
182
+ when String
183
+ @to = File.open(to)
184
+ when IO
185
+ @to = to
186
+ else
187
+ raise "I don't know what to do"
188
+ end
189
+ end
190
+
191
+ def write(str)
192
+ @to.write(str)
193
+ end
194
+
195
+ def puts(str)
196
+ @to.puts(str)
197
+ end
198
+
199
+ def flush
200
+ @to.flush
201
+ end
202
+
203
+ end
@@ -0,0 +1,38 @@
1
+ class CaseStub
2
+ def initialize(value, &block)
3
+ @value = value
4
+ @block = block
5
+ end
6
+
7
+ def __handle(buffer)
8
+ handler = CaseHandler.new(buffer)
9
+ buffer << "case #{@value} in"
10
+ buffer.indent
11
+ @block.call(handler)
12
+ buffer.undent
13
+ buffer << "esac"
14
+ end
15
+ end
16
+
17
+
18
+ class CaseHandler
19
+ def initialize(buffer)
20
+ @buffer = buffer
21
+ end
22
+
23
+ def __escapinate(v)
24
+ if v.empty?
25
+ '""'
26
+ else
27
+ v
28
+ end
29
+ end
30
+
31
+ def when(opt, &block)
32
+ @buffer << "#{__escapinate(opt.to_s)})"
33
+ @buffer.indent
34
+ yield
35
+ @buffer.undent
36
+ @buffer << ";;"
37
+ end
38
+ end
@@ -0,0 +1,15 @@
1
+ module Escaping
2
+ def __escapinate(v)
3
+ case v
4
+ when RawString
5
+ v.quote
6
+ when BareString
7
+ v
8
+ when String
9
+ "'#{v.gsub(/'/, "\\'").gsub("\\", "\\\\")}'"
10
+ when Fixnum
11
+ v
12
+ end
13
+ end
14
+ end
15
+
@@ -0,0 +1,17 @@
1
+ class ForStub
2
+ include ::Escaping
3
+
4
+ def initialize(over, iter, &block)
5
+ @over = over
6
+ @iter = iter
7
+ @block = block
8
+ end
9
+
10
+ def __handle(buffer)
11
+ buffer << "for #{@iter} in #{__escapinate(@over)}; do"
12
+ buffer.indent
13
+ @block.call
14
+ buffer.undent
15
+ buffer << "done"
16
+ end
17
+ end
@@ -0,0 +1,40 @@
1
+ class IfStub
2
+ def initialize(condition, &block)
3
+ @condition = condition
4
+ @block = block
5
+ end
6
+
7
+ def __handle(buffer)
8
+ handler = IfHandler.new(buffer)
9
+ buffer << "if #{@condition}"
10
+ @block.call(handler)
11
+ buffer << "fi"
12
+ end
13
+ end
14
+
15
+ class IfHandler
16
+ def initialize(buffer)
17
+ @buffer = buffer
18
+ end
19
+
20
+ def then(&block)
21
+ @buffer << "then"
22
+ @buffer.indent
23
+ block.call
24
+ @buffer.undent
25
+ end
26
+
27
+ def elseif(condition, &block)
28
+ @buffer << "else if #{condition}"
29
+ @buffer.indent
30
+ block.call
31
+ @buffer.undent
32
+ end
33
+
34
+ def else(&block)
35
+ @buffer << "else"
36
+ @buffer.indent
37
+ block.call
38
+ @buffer.undent
39
+ end
40
+ end
data/proof_of_concept.rb CHANGED
@@ -1,22 +1,60 @@
1
- require './shell_proxy'
1
+ require './lib/shell-proxy'
2
2
 
3
3
  ShellProxy.new.__main__ do
4
4
  cd "Somedir"
5
5
 
6
+ __function("butts_function") do
7
+ touch "butts"
8
+ end
9
+
6
10
  __subshell do
7
11
  __subshell do
8
12
  mkdir "borp"
9
13
  cd "borp"
10
14
  touch "thing"
11
15
  end
12
- touch "somefile"
16
+ %w[foo bar baz].each do |dir|
17
+ mkdir dir
18
+ touch "#{dir}/#{dir}"
19
+ end
20
+ touch("somefile")
13
21
  mkdir "foo/bar/thing", { :p => nil }
22
+ echo("foo") | wc({:c => nil})
14
23
  end
15
24
 
16
25
  __chdir "/tmp" do
17
26
  touch "rawr"
18
27
  end
19
28
 
29
+ __set("foo", bare("$RANDOM"))
30
+
31
+ some | thing | some | other | thing
32
+
33
+ __case(raw("$foo")) do |c|
34
+ c.when(10000) do
35
+ echo "holy shit, did not expect that"
36
+ end
37
+ c.when("*") do
38
+ echo "Welp, that was predictable"
39
+ end
40
+ end
41
+
42
+ __for(bare("foo bar baz"), "i") do
43
+ echo raw("$i")
44
+ end
45
+
20
46
  rm "foo", { :r => nil, :f => nil }
21
47
  mongod({ :config => "/usr/local/etc/mongod.conf" })
48
+
49
+ __if(raw("[[ $foo == 'foo' ]]")) do |c|
50
+ c.then do
51
+ echo "it was true"
52
+ end
53
+ c.elseif(raw("[[ bar == bar ]]")) do
54
+ echo "this is definitely true"
55
+ end
56
+ c.else do
57
+ echo "This wont be reached"
58
+ end
59
+ end
22
60
  end
data/shell-proxy.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "shell-proxy"
5
- s.version = "0.0.0"
5
+ s.version = "0.0.1"
6
6
  s.authors = ["Richo Healey"]
7
7
  s.email = ["richo@psych0tik.net"]
8
8
  s.homepage = "http://github.com/richo/shell-proxy"
data/test_shell_proxy.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require 'rspec'
2
- require File.expand_path("../shell_proxy.rb", __FILE__)
2
+ require File.expand_path("../lib/shell-proxy.rb", __FILE__)
3
3
 
4
4
  describe "ShellProxy" do
5
5
  before(:each) do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shell-proxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-06 00:00:00.000000000 Z
12
+ date: 2013-04-18 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: description
15
15
  email:
@@ -18,14 +18,19 @@ executables: []
18
18
  extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
+ - .gitignore
21
22
  - Makefile
22
23
  - README.md
23
24
  - README/1
24
25
  - README/2
25
26
  - README/3
27
+ - lib/shell-proxy.rb
28
+ - lib/shell-proxy/case.rb
29
+ - lib/shell-proxy/escaping.rb
30
+ - lib/shell-proxy/for.rb
31
+ - lib/shell-proxy/if.rb
26
32
  - proof_of_concept.rb
27
33
  - shell-proxy.gemspec
28
- - shell_proxy.rb
29
34
  - test_shell_proxy.rb
30
35
  homepage: http://github.com/richo/shell-proxy
31
36
  licenses: []
data/shell_proxy.rb DELETED
@@ -1,105 +0,0 @@
1
- class ShellProxy
2
-
3
- INDENT_PADDING=" "
4
-
5
- def initialize
6
- @indent = 0
7
- end
8
-
9
- def __main__(&block)
10
- instance_exec(&block)
11
- end
12
-
13
- def __subshell(&block)
14
- __emit("(")
15
- @indent += 1
16
- yield
17
- @indent -= 1
18
- __emit(")")
19
- end
20
-
21
- def __chdir(dir, &block)
22
- __subshell do
23
- cd(dir)
24
- yield
25
- end
26
- end
27
-
28
- def method_missing(sym, *args)
29
- opts = case args[-1]
30
- when Hash
31
- args.pop
32
- else
33
- {}
34
- end
35
-
36
- cmd = sym.to_s
37
- cmd << " #{__process_opts(opts)}" unless opts.empty?
38
- cmd << " #{__process_args(args)}" unless args.empty?
39
- __emit cmd
40
- end
41
-
42
- def __emit(str)
43
- __writer.write(INDENT_PADDING * @indent)
44
- __writer.puts(str)
45
- __writer.flush
46
- end
47
-
48
- def __writer
49
- @writer ||= ShellWriter.new($stdout)
50
- end
51
-
52
- def __process_args(args)
53
- args.map do |v|
54
- __escapinate(v)
55
- end.join(" ")
56
- end
57
-
58
- def __process_opts(opts)
59
- outputs = []
60
- __process_and_escape(opts) do |value|
61
- outputs << value
62
- end
63
- outputs.join(" ")
64
- end
65
-
66
- def __process_and_escape(opts)
67
- opts.each do |k, v|
68
- k = k.to_s
69
- k = (k.length == 1 ? "-" : "--") + k
70
- yield __escapinate(k)
71
- yield __escapinate(v) unless v.nil?
72
- end
73
- end
74
-
75
- def __escapinate(v)
76
- "'#{v.gsub(/'/, "\\'").gsub("\\", "\\\\")}'"
77
- end
78
-
79
- end
80
-
81
- class ShellWriter
82
- def initialize(to)
83
- case to
84
- when String
85
- @to = File.open(to)
86
- when IO
87
- @to = to
88
- else
89
- raise "I don't know what to do"
90
- end
91
- end
92
-
93
- def write(str)
94
- @to.write(str)
95
- end
96
-
97
- def puts(str)
98
- @to.puts(str)
99
- end
100
-
101
- def flush
102
- @to.flush
103
- end
104
-
105
- end