pry-remote-em 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,258 @@
1
+ # What is it?
2
+
3
+ A way to start Pry remotely in EventMachine and to connect to it. This provides access to the state of the running program from anywhere.
4
+
5
+ It's based off of [Mon-Ouie's](https://github.com/Mon-Ouie) [pry-remote](https://github.com/Mon-Ouie/pry-remote) for DRb.
6
+
7
+ # Compatibility
8
+
9
+ MRI 1.9 or any other VM with support for Fibers is required.
10
+
11
+
12
+ # Installation
13
+
14
+ ```bash
15
+ gem install pry-remote-em
16
+ ```
17
+
18
+ # Usage
19
+
20
+ ```ruby
21
+ require 'pry-remote-em/server'
22
+
23
+ class Foo
24
+ def initialize(x, y)
25
+ binding.remote_pry_em
26
+ end
27
+ end
28
+
29
+ EM.run { Foo.new 10, 20 }
30
+ ```
31
+
32
+ Running it will print out a message telling you Pry is waiting for a
33
+ program to connect itself to it:
34
+
35
+ [pry-remote-em] listening for connections on pryem://localhost:6462/
36
+
37
+ You can then connect to the pry session using ``pry-remote-em``:
38
+
39
+ $ pry-remote-em
40
+ [pry-remote-em] client connected to pryem://127.0.0.1:6462/
41
+ [pry-remote-em] remote is PryRemoteEm 0.1.0
42
+ [1] pry(#<Foo>)> stat
43
+ Method Information:
44
+ --
45
+ Name: initialize
46
+ Owner: Foo
47
+ Visibility: private
48
+ Type: Bound
49
+ Arity: 2
50
+ Method Signature: initialize(x, y)
51
+ Source Location: (irb):2
52
+
53
+ [2] pry(#<Foo>)> self
54
+ => #<Foo:0x007fe66a426fa0>
55
+
56
+ [3] pry(#<Foo>)> ls
57
+ locals: _ _dir_ _ex_ _file_ _in_ _out_ _pry_ x y
58
+ [4] pry(#<Foo>)> x
59
+ => 10
60
+
61
+ [5] pry(#<Foo>)> x = 12
62
+ => 12
63
+
64
+ [6] pry(#<Foo>)> x
65
+ => 12
66
+
67
+ [7] pry(#<Foo>)> exit
68
+ [pry-remote-em] session terminated
69
+
70
+ $ pry-remote-em
71
+ [pry-remote-em] client connected to pryem://127.0.0.1:6462/
72
+ [pry-remote-em] remote is PryRemoteEm 0.1.0
73
+ [1] pry(#<Foo>)> x
74
+ => 12
75
+
76
+ [2] pry(#<Foo>)> exit
77
+ [pry-remote-em] session terminated
78
+
79
+ # Features
80
+
81
+ ## TLS Encryption
82
+
83
+ When creating a server pass the :tls => true option to enable TLS. If
84
+ you pass a Hash, e.g. ``:tls => {:private_key_file => '/tmp/server.key'}`` it will be used to configure the internal TLS handler.
85
+ See [EventMachine::Connection#start_tls](http://eventmachine.rubyforge.org/EventMachine/Connection.html#M000296) for the available options.
86
+
87
+ To start the command line client in TLS mode pass it a pryems URL instead of a pryem URL.
88
+
89
+ ```bash
90
+ $ bin/pry-remote-em pryems:///
91
+ [pry-remote-em] client connected to pryem://127.0.0.1:6462/
92
+ [pry-remote-em] remote is PryRemoteEm 0.2.0 pryems
93
+ [pry-remote-em] negotiating TLS
94
+ [pry-remote-em] TLS connection established
95
+ [1] pry(#<Hash>)>
96
+ ```
97
+
98
+ ## User Authentication
99
+
100
+ ### Server
101
+
102
+ If the service is started with the :auth option it will require all
103
+ clients to authenticate on connect. The :auth option can be a Hash, proc
104
+ or any object that responds to #call.
105
+
106
+ #### Auth with a Hash
107
+ ```ruby
108
+ auth_hash = {'caleb' => 'crane', 'john' => 'lowski'}
109
+ obj = {:encoding => __ENCODING__, :weather => :cloudy}
110
+ EM.run{
111
+ obj.remote_pry_em('localhost', :auto, :tls => true, :auth => auth_hash)
112
+ }
113
+ ```
114
+
115
+ #### Auth with a lambda
116
+ ```ruby
117
+ require ‘net/ldap’
118
+ ldap_anon = lambda do |user, pass|
119
+ ldap = Net::LDAP.new :host => “10.0.0.1”, :port => 389, :auth => {:method => :simple, :username => user, :password => pass}
120
+ ldap.bind
121
+ end
122
+ obj = {:encoding => __ENCODING__, :weather => :cloudy}
123
+ EM.run{
124
+ obj.remote_pry_em('localhost', :auto, :tls => true, :auth => ldap_anon)
125
+ }
126
+ ```
127
+
128
+ #### Auth with an object
129
+ ```ruby
130
+ class Authenticator
131
+ def initialize(db)
132
+ @db = db
133
+ end
134
+ def call(user, pass)
135
+ @db[user] && @db[user] == pass
136
+ end
137
+ end
138
+
139
+ obj = {:encoding => __ENCODING__, :weather => :cloudy}
140
+ EM.run{
141
+ obj.remote_pry_em('localhost', :auto, :tls => true, :auth => Authenticator.new(auth_hash))
142
+ }
143
+ ```
144
+
145
+
146
+ ### Client
147
+
148
+ The included command line client ``pry-remote-em`` can take a username
149
+ and/or password as part of the url argument. If either a username or
150
+ password is not supplied, but required by the server it will prompt for
151
+ them.
152
+
153
+ ```shell
154
+ $ pry-remote-em pryems://localhost:6464/
155
+ [pry-remote-em] client connected to pryem://127.0.0.1:6464/
156
+ [pry-remote-em] remote is PryRemoteEm 0.4.0 pryems
157
+ [pry-remote-em] negotiating TLS
158
+ [pry-remote-em] TLS connection established
159
+ user: caleb
160
+ caleb's password: *****
161
+ [1] pry(#<Hash>)>
162
+ ```
163
+
164
+
165
+ ```shell
166
+ $ pry-remote-em pryems://caleb@localhost:6464
167
+ [pry-remote-em] client connected to pryem://127.0.0.1:6464/
168
+ [pry-remote-em] remote is PryRemoteEm 0.4.0 pryems
169
+ [pry-remote-em] negotiating TLS
170
+ [pry-remote-em] TLS connection established
171
+ caleb's password: *****
172
+ [1] pry(#<Hash>)> exit
173
+ ```
174
+
175
+ ```shell
176
+ $ pry-remote-em pryems://caleb:crane@localhost:6464
177
+ [pry-remote-em] client connected to pryem://127.0.0.1:6464/
178
+ [pry-remote-em] remote is PryRemoteEm 0.4.0 pryems
179
+ [pry-remote-em] negotiating TLS
180
+ [pry-remote-em] TLS connection established
181
+ [1] pry(#<Hash>)> exit
182
+ ```
183
+
184
+
185
+ ## Tab Completion
186
+
187
+ Tab completion candidates will be retrieved from the server and
188
+ presented on the client side.
189
+
190
+ ```ruby
191
+ $ bin/pry-remote-em pryems:///
192
+ [pry-remote-em] client connected to pryem://127.0.0.1:6462/
193
+ [pry-remote-em] remote is PryRemoteEm 0.2.0 pryems
194
+ [1] pry(#<Hash>)> key (^TAB ^TAB)
195
+ key key? keys
196
+ [1] pry(#<Hash>)> keys
197
+ => [:encoding]
198
+ ```
199
+
200
+ ## Paging
201
+
202
+ The standard Pry pager is supported through the included client.
203
+
204
+ ```ruby
205
+ [1] pry(#<Hash>)> ENV
206
+ => {"COMMAND_MODE"=>"unix2003",
207
+ "DISPLAY"=>"/tmp/launch-0EGhJW/org.x:0",
208
+ "EDITOR"=>"mvim -f --nomru -c \"au VimLeave * !open -a Terminal\"",
209
+ "GEM_HOME"=>"/Users/caleb/.rvm/gems/ruby-1.9.2-p290",
210
+ "GEM_PATH"=>
211
+ "/Users/caleb/.rvm/gems/ruby-1.9.2-p290:/Users/caleb/.rvm/gems/ruby-1.9.2-p290@global",
212
+ "GREP_COLOR"=>"1;32",
213
+ "GREP_OPTIONS"=>"--color=auto",
214
+ "HOME"=>"/Users/caleb",
215
+ "IRBRC"=>"/Users/caleb/.rvm/rubies/ruby-1.9.2-p290/.irbrc",
216
+ "LC_CTYPE"=>"",
217
+ "LOGNAME"=>"caleb",
218
+ "LSCOLORS"=>"Gxfxcxdxbxegedabagacad",
219
+ :
220
+ ```
221
+
222
+ # Missing Features
223
+
224
+ - AutoDiscovery/Broker [ticket](https://github.com/simulacre/pry-remote-em/issues/11)
225
+ - HTTP Transport [ticket](https://github.com/simulacre/pry-remote-em/issues/12)
226
+ - Shell Commands [ticket](https://github.com/simulacre/pry-remote-em/issues/15)
227
+ - Vi mode editing - RbReadline doesn't support vi edit mode. I'm looking into contributing it. PryRemoteEm uses rb-readline because the STLIB version doesn't play nice with Fibers.
228
+ - Ssh key based authentication
229
+
230
+
231
+ # Issues
232
+
233
+ Please post any bug reports or feature requests on [Github](https://github.com/simulacre/pry-remote-em/issues)
234
+
235
+
236
+
237
+
238
+ # Copyright
239
+
240
+ Copyright (c) 2012 Caleb Crane
241
+
242
+ Permission is hereby granted, free of charge, to any person obtaining a
243
+ copy of this software and associated documentation files (the "Software"),
244
+ to deal in the Software without restriction, including without limitation
245
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
246
+ and/or sell copies of the Software, and to permit persons to whom the
247
+ Software is furnished to do so, subject to the following conditions:
248
+
249
+ The above copyright notice and this permission notice shall be included
250
+ in all copies or substantial portions of the Software.
251
+
252
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
253
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
254
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
255
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
256
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
257
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
258
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/bin/pry-remote-em ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'uri'
4
+ require 'highline'
5
+ require 'pry-remote-em/client'
6
+
7
+ uri = ARGV[0] || "pryem://localhost:#{PryRemoteEm::DEFPORT}"
8
+ uri = URI.parse(uri)
9
+ unless %w(pryem pryems).include?(uri.scheme)
10
+ abort "only pryem URIs are currently supported\n usage: pryem(s)://127.0.0.1:#{PryRemoteEm::DEFPORT}"
11
+ end
12
+
13
+ tried = 0
14
+ auth_proc = proc do
15
+ tried += 1
16
+ user = uri.user || ($stdin.tty? ? Readline.readline("user: ") : raise("username is require for authentication"))
17
+ pass = if !uri.password.nil? && tried <= 1
18
+ uri.password
19
+ elsif $stdin.tty?
20
+ HighLine.new.ask("#{user}'s password: ") { |q| q.echo = '*'}
21
+ else
22
+ raise "password is required to authenticate"
23
+ end
24
+ [user, pass]
25
+ end
26
+
27
+ EM.run do
28
+ PryRemoteEm::Client.start(uri.host, uri.port, :auth=>auth_proc, :tls=>uri.scheme=='pryems') { |e| EM.stop }
29
+ end
@@ -0,0 +1,25 @@
1
+ begin
2
+ require 'openssl'
3
+ rescue LoadError
4
+ warn "OpenSSL support is not available"
5
+ end
6
+ require 'pry-remote-em/version'
7
+ require 'pry-remote-em/json-proto'
8
+ require 'eventmachine'
9
+ require 'socket'
10
+ require 'json'
11
+ require "fiber"
12
+
13
+ module PryRemoteEm
14
+ DEFHOST = 'localhost'
15
+ DEFPORT = 6462
16
+ NEGOTIMER = 15
17
+ end
18
+
19
+
20
+ class Object
21
+ def remote_pry_em(host = PryRemoteEm::DEFHOST, port = PryRemoteEm::DEFPORT, opts = {:tls => false})
22
+ opts = {:target => self}.merge(opts)
23
+ PryRemoteEm::Server.run(opts[:target], host, port, opts)
24
+ end
25
+ end
@@ -0,0 +1,128 @@
1
+ require 'uri'
2
+ require 'pry-remote-em'
3
+ require 'pry/helpers/base_helpers'
4
+ #require "readline" # doesn't work with Fiber.yield
5
+ # - /Users/caleb/src/pry-remote-em/lib/pry-remote-em/client.rb:45:in `yield': fiber called across stack rewinding barrier (FiberError)
6
+ require "rb-readline" # doesn't provide vi-mode support :(
7
+ # https://github.com/luislavena/rb-readline/issues/21
8
+ # https://github.com/simulacre/rb-readline/commit/0376eb4e9526b3dc1a6512716322efcef409628d
9
+
10
+ module PryRemoteEm
11
+ module Client
12
+ include EM::Deferrable
13
+ include JsonProto
14
+ include Pry::Helpers::BaseHelpers
15
+
16
+ class << self
17
+ def start(host = PryRemoteEm::DEFHOST, port = PryRemoteEM::DEFPORT, opts = {:tls => false})
18
+ EM.connect(host || PryRemoteEm::DEFHOST, port || PryRemoteEm::DEFPORT, PryRemoteEm::Client, opts) do |c|
19
+ c.callback { yield if block_given? }
20
+ c.errback do |e|
21
+ puts "[pry-remote-em] connection failed\n#{e}"
22
+ yield(e) if block_given?
23
+ end
24
+ end
25
+ end
26
+ end # class << self
27
+
28
+ def initialize(opts = {})
29
+ @opts = opts
30
+ if (a = opts[:auth])
31
+ if a.respond_to?(:call)
32
+ @auth = a
33
+ else
34
+ @auth = lambda { a }
35
+ end
36
+ end
37
+ end
38
+
39
+ def post_init
40
+ return fail("connection was not established") unless get_peername
41
+ port, ip = Socket.unpack_sockaddr_in(get_peername)
42
+ Kernel.puts "[pry-remote-em] client connected to pryem://#{ip}:#{port}/"
43
+ @nego_timer = EM::Timer.new(PryRemoteEm::NEGOTIMER) do
44
+ fail("[pry-remote-em] server didn't finish negotiation within #{PryRemoteEm::NEGOTIMER} seconds; terminating")
45
+ end
46
+ Readline.completion_proc = method(:auto_complete)
47
+ end
48
+
49
+ def auto_complete(word)
50
+ @waiting = Fiber.current
51
+ send_data({:c => word})
52
+ return Fiber.yield
53
+ end
54
+
55
+ def receive_json(j)
56
+ if j['p'] # prompt
57
+ if @negotiated && !@unbound
58
+ Fiber.new { send_data(Readline.readline(j['p'], true)) }.resume
59
+ end
60
+
61
+ elsif j['d'] # printable data
62
+ stagger_output j['d'], $stdout # Pry::Helpers::BaseHelpers
63
+
64
+ elsif j['g'] # server banner
65
+ Kernel.puts "[pry-remote-em] remote is #{j['g']}"
66
+ name, version, scheme = j['g'].split(" ", 3)
67
+ # TODO parse version and compare against a Gem style matcher
68
+ # https://github.com/simulacre/pry-remote-em/issues/21
69
+ return fail("[pry-remote-em] incompatible version #{version}") if version != PryRemoteEm::VERSION
70
+ if scheme.nil? || scheme != (reqscheme = @opts[:tls] ? 'pryems' : 'pryem')
71
+ if scheme == 'pryems' && defined?(::OpenSSL)
72
+ @opts[:tls] = true
73
+ else
74
+ return fail("[pry-remote-em] server doesn't support required scheme #{reqscheme.dump}")
75
+ end # scheme == 'pryems' && defined?(::OpenSSL)
76
+ end
77
+ @nego_timer.cancel
78
+ @negotiated = true
79
+ start_tls if @opts[:tls]
80
+
81
+ elsif j['c'] # tab completion response
82
+ @waiting, f = nil, @waiting
83
+ f.resume(j['c']) if f
84
+
85
+ elsif j.include?('a') # authentication demand
86
+ return fail j['a'] if j['a'].is_a?(String)
87
+ return authenticate if j['a'] == false
88
+ @authenticated = true if j['a'] == true
89
+
90
+ else
91
+ warn "[pry-remote-em] received unexpected data: #{j.inspect}"
92
+ end
93
+ end
94
+
95
+ def authenticate
96
+ return fail("[pry-remote-em] authentication required") unless @auth
97
+ return fail("[pry-remote-em] can't authenticate before negotiation complete") unless @negotiated
98
+ user, pass = @auth.call
99
+ return fail("[pry-remote-em] expected #{@auth} to return a user and password") unless user && pass
100
+ send_data({:a => [user, pass]})
101
+ end # authenticate
102
+
103
+ def ssl_handshake_completed
104
+ Kernel.puts "[pry-remote-em] TLS connection established"
105
+ end
106
+
107
+ def start_tls
108
+ Kernel.puts "[pry-remote-em] negotiating TLS"
109
+ super(@opts[:tls].is_a?(Hash) ? @opts[:tls] : {})
110
+ end
111
+
112
+ def unbind
113
+ @unbound = true
114
+ Kernel.puts "[pry-remote-em] session terminated"
115
+ # prior to 1.0.0.b4 error? returns true here even when it's not
116
+ return succeed if Gem.loaded_specs["eventmachine"].version < Gem::Version.new("1.0.0.beta4")
117
+ error? ? fail : succeed
118
+ end
119
+ end # module::Client
120
+ end # module::PryRemoteEm
121
+
122
+ # Pry::Helpers::BaseHelpers#stagger_output expects Pry.pager to be defined
123
+ class Pry
124
+ class << self
125
+ attr_accessor :pager unless respond_to?(:pager)
126
+ end
127
+ end
128
+ Pry.pager = true
@@ -0,0 +1,30 @@
1
+ require 'json'
2
+
3
+ module PryRemoteEm
4
+ module JsonProto
5
+ DELIM = ']]>]]><[[<[['
6
+
7
+ def receive_data(d)
8
+ return unless d && d.length > 0
9
+ @buffer ||= "" # inlieu of a post_init
10
+
11
+ if six = d.index(DELIM)
12
+ @buffer << d[0...six]
13
+ j = JSON.load(@buffer)
14
+ @buffer.clear
15
+ receive_json(j)
16
+ receive_data(d[(six + DELIM.length)..-1])
17
+ else
18
+ @buffer << d
19
+ end
20
+ end
21
+
22
+ def receive_json(j)
23
+ end
24
+
25
+ def send_data(d)
26
+ super(JSON.dump(d.is_a?(String) ? {:d => d} : d) + DELIM)
27
+ end
28
+
29
+ end # module::JsonProto
30
+ end # module::PryRemoteEm
@@ -0,0 +1,168 @@
1
+ require 'pry'
2
+ require 'pry-remote-em'
3
+
4
+ module PryRemoteEm
5
+ module Server
6
+ include JsonProto
7
+
8
+ class << self
9
+ def run(obj, host = DEFHOST, port = DEFPORT, opts = {:tls => false})
10
+ tries = :auto == port ? 100.tap{ port = DEFPORT } : 1
11
+ # TODO raise a useful exception not RuntimeError
12
+ raise "root permission required for port below 1024 (#{port})" if port < 1024 && Process.euid != 0
13
+ begin
14
+ EM.start_server(host, port, PryRemoteEm::Server, opts) do |pre|
15
+ Fiber.new {
16
+ begin
17
+ Pry.start(obj, :input => pre, :output => pre)
18
+ ensure
19
+ pre.close_connection
20
+ end
21
+ }.resume
22
+ end
23
+ rescue => e
24
+ # EM 1.0.0.beta4's message tells us the port is in use; 0.12.10 just says, 'no acceptor'
25
+ if (e.message.include?('port is in use') || e.message.include?('no acceptor')) && tries >= 1
26
+ tries -= 1
27
+ port += 1
28
+ retry
29
+ end
30
+ raise e
31
+ end
32
+ scheme = opts[:tls] ? 'pryems' : 'pryem'
33
+ Kernel.puts "[pry-remote-em] listening for connections on #{scheme}://#{host}:#{port}/"
34
+ end # run(obj, host = DEFHOST, port = DEFPORT)
35
+ end # class << self
36
+
37
+ def initialize(opts = {:tls => false})
38
+ @after_auth = []
39
+ @opts = opts
40
+ if (a = opts[:auth])
41
+ if a.respond_to?(:call)
42
+ return error("auth handler procs must take two arguments") unless a.method(:call).arity == 2
43
+ @auth = a
44
+ else
45
+ return error("auth handler objects must respond to :call, or :[]") unless a.respond_to?(:[])
46
+ @auth = lambda {|u,p| a[u] && a[u] == p }
47
+ end
48
+ @auth_tries = 5
49
+ end
50
+ end
51
+
52
+ def post_init
53
+ @lines = []
54
+ Pry.config.pager, @old_pager = false, Pry.config.pager
55
+ Pry.config.system, @old_system = PryRemoteEm::Server::System, Pry.config.system
56
+ @auth_required = @auth
57
+ port, ip = Socket.unpack_sockaddr_in(get_peername)
58
+ Kernel.puts "[pry-remote-em] received client connection from #{ip}:#{port}"
59
+ send_data({:g => "PryRemoteEm #{VERSION} #{@opts[:tls] ? 'pryems' : 'pryem'}"})
60
+ @opts[:tls] ? start_tls : (@auth_required && send_data({:a => false}))
61
+ end
62
+
63
+ def start_tls
64
+ Kernel.puts "[pry-remote-em] starting TLS (#{peer_ip}:#{peer_port})"
65
+ super(@opts[:tls].is_a?(Hash) ? @opts[:tls] : {})
66
+ end
67
+
68
+ def ssl_handshake_completed
69
+ Kernel.puts "[pry-remote-em] TLS connection established (#{peer_ip}:#{peer_port})"
70
+ send_data({:a => false}) if @auth_required
71
+ end
72
+
73
+ def peer_ip
74
+ return @peer_ip if @peer_ip
75
+ return "" if get_peername.nil?
76
+ @peer_port, @peer_ip = Socket.unpack_sockaddr_in(get_peername)
77
+ @peer_ip
78
+ end
79
+
80
+ def peer_port
81
+ return @peer_port if @peer_port
82
+ return "" if get_peername.nil?
83
+ @peer_port, @peer_ip = Socket.unpack_sockaddr_in(get_peername)
84
+ @peer_port
85
+ end
86
+
87
+ def receive_json(j)
88
+ return send_data({:a => false}) if @auth_required && !j['a']
89
+
90
+ if j['d'] # just normal data
91
+ @lines.push(*j['d'].split("\n"))
92
+ if @waiting
93
+ f, @waiting = @waiting, nil
94
+ f.resume(@lines.shift)
95
+ end
96
+ elsif j['c'] # tab completion request
97
+ send_data({:c => @compl_proc.call(j['c'])})
98
+
99
+ elsif j['a'] # authentication response
100
+ return send_data({:a => true}) if !@auth || !@auth_required
101
+ return send_data({:a => 'auth data must be a two element array'}) unless j['a'].is_a?(Array) && j['a'].length == 2
102
+ unless (@auth_required = !@auth.call(*j['a']))
103
+ authenticated!
104
+ else
105
+ if @auth_tries <= 0
106
+ msg = "max authentication attempts reached"
107
+ send_data({:a => msg})
108
+ Kernel.puts "[pry-remote-em] #{msg} (#{peer_ip}:#{peer_port})"
109
+ return close_connection_after_writing
110
+ end
111
+ @auth_tries -= 1
112
+ end
113
+ return send_data({:a => !@auth_required})
114
+
115
+ else
116
+ warn "received unexpected data: #{j.inspect}"
117
+ end # j['d']
118
+ end # receive_json(j)
119
+
120
+
121
+ def authenticated!
122
+ while (aa = @after_auth.shift)
123
+ send_data(aa)
124
+ end
125
+ end
126
+
127
+ def unbind
128
+ Pry.config.pager = @old_pager
129
+ Pry.config.system = @old_system
130
+ Kernel.puts "[pry-remote-em] remote session terminated (#{peer_ip}:#{peer_port})"
131
+ end
132
+
133
+ # Methods that make Server compatible with Pry
134
+
135
+ def readline(prompt)
136
+ @auth_required ? @after_auth.push({:p => prompt}) : send_data({:p => prompt})
137
+ return @lines.shift unless @lines.empty?
138
+ @waiting = Fiber.current
139
+ return Fiber.yield
140
+ end
141
+
142
+ def print(val)
143
+ send_data({:d => val})
144
+ end
145
+ alias :write :print
146
+
147
+ def puts(data = "")
148
+ s = data.to_s
149
+ print(s[0] == "\n" ? s : s + "\n")
150
+ end
151
+
152
+ def completion_proc=(compl)
153
+ @compl_proc = compl
154
+ end
155
+
156
+ def tty?
157
+ true # might be a very bad idea ....
158
+ end
159
+
160
+ def flush
161
+ true
162
+ end
163
+
164
+ System = proc do |output, cmd, _|
165
+ output.puts("shell commands are not yet supported")
166
+ end
167
+ end # module::Server
168
+ end # module::PryRemoteEm
@@ -0,0 +1,3 @@
1
+ module PryRemoteEm
2
+ VERSION = '0.4.0'
3
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pry-remote-em
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Caleb Crane
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-01-28 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: eventmachine
16
+ requirement: &70305814043480 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70305814043480
25
+ - !ruby/object:Gem::Dependency
26
+ name: pry
27
+ requirement: &70305814042980 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.9.6
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70305814042980
36
+ - !ruby/object:Gem::Dependency
37
+ name: rb-readline
38
+ requirement: &70305814042560 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70305814042560
47
+ - !ruby/object:Gem::Dependency
48
+ name: highline
49
+ requirement: &70305814042100 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70305814042100
58
+ description: Connect to Pry remotely using EventMachine with tab-completion, paging,
59
+ user authentication and SSL support.
60
+ email: pry-remote-em@simulacre.org
61
+ executables:
62
+ - pry-remote-em
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - lib/pry-remote-em/client.rb
67
+ - lib/pry-remote-em/json-proto.rb
68
+ - lib/pry-remote-em/server.rb
69
+ - lib/pry-remote-em/version.rb
70
+ - lib/pry-remote-em.rb
71
+ - bin/pry-remote-em
72
+ - README.md
73
+ homepage: http://github.com/simulacre/pry-remote-em
74
+ licenses: []
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ none: false
87
+ requirements:
88
+ - - ! '>='
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubyforge_project:
93
+ rubygems_version: 1.8.10
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: Connect to Pry remotely using EventMachine
97
+ test_files: []