pry-remote-em 0.7.5 → 1.0.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.
@@ -1,34 +1,38 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'uri'
4
+ require 'readline'
4
5
  require 'highline'
5
6
  require 'pry-remote-em/client'
6
7
  require 'optparse'
7
8
 
8
9
  options = {}
9
10
  OptionParser.new do |opts|
10
- opts.on("-c", "--connect NAME", "connect to the first pry remote em server matching NAME") do |name|
11
+ opts.on('-c', '--connect NAME', 'connect to the first pry remote em server matching NAME') do |name|
11
12
  options[:connect] = name
12
- end
13
- opts.on("-p", "--proxy NAME", "proxy through the broker to the first pry remote em server matching NAME") do |name|
13
+ end
14
+ opts.on('-p', '--proxy NAME', 'proxy through the broker to the first pry remote em server matching NAME') do |name|
14
15
  options[:proxy] = name
15
- end
16
+ end
17
+ opts.on('-P', '--proxy-by-default', 'show servers table with proxy mode enabled by default (ignored on -c or -p)') do |name|
18
+ options[:proxy_by_default] = true
19
+ end
16
20
 
17
- opts.on("--fh HOST", "--filter-host HOST", "only show servers listening at the given address (regexp)") do |host|
21
+ opts.on('--fh HOST', '--filter-host HOST', 'only show servers listening at the given address (regexp)') do |host|
18
22
  if host =~ /^pryems?:\/\//
19
23
  ARGV.push(host)
20
- else
24
+ else
21
25
  options[:filter_host] = Regexp.new(host)
22
- end
23
- end
24
- opts.on("--fn NAME", "--filter-name NAME", "only show servers with a matching name (regexp)") do |name|
26
+ end
27
+ end
28
+ opts.on('--fn NAME', '--filter-name NAME', 'only show servers with a matching name (regexp)') do |name|
25
29
  if name =~ /^pryems?:\/\//
26
30
  ARGV.push(name)
27
- else
31
+ else
28
32
  options[:filter_name] = Regexp.new(name)
29
- end
33
+ end
30
34
  end
31
- opts.on("--[no-]fs", "--[no-]filter-ssl", "show only servers that support ssl") do |ssl|
35
+ opts.on('--[no-]fs', '--[no-]filter-ssl', 'show only servers that support ssl') do |ssl|
32
36
  options[:filter_ssl] = ssl
33
37
  end
34
38
 
@@ -37,30 +41,45 @@ OptionParser.new do |opts|
37
41
  opts.on('--sp', '--sort-port', 'sort by port') { options[:sort] = :port }
38
42
  opts.on('--ss', '--sort-ssl', 'sort by ssl support') { options[:sort] = :ssl }
39
43
 
44
+ opts.on('-d', '--details KEY', "show value from server's details option by given key instead of url in table, use @ to show all details") do |key|
45
+ options[:show_details] = key
46
+ end
47
+
48
+ opts.on('-i', '--ignore-localhost', 'filter out localhost urls from list') do
49
+ options[:ignore_localhost] = true
50
+ end
51
+
40
52
  opts.parse!(ARGV)
41
- end
53
+ end
42
54
 
43
- uri = ARGV[0] || "pryem://localhost:#{PryRemoteEm::DEF_BROKERPORT}"
55
+ uri = if ARGV[0].nil? || ARGV[0].empty?
56
+ host = ENV['PRYEMBROKER'].nil? || ENV['PRYEMBROKER'].empty? ? PryRemoteEm::DEFAULT_BROKER_HOST : ENV['PRYEMBROKER']
57
+ port = ENV['PRYEMBROKERPORT'].nil? || ENV['PRYEMBROKERPORT'].empty? ? PryRemoteEm::DEFAULT_BROKER_PORT : ENV['PRYEMBROKERPORT']
58
+ "pryem://#{host}:#{port}"
59
+ else
60
+ ARGV[0]
61
+ end
44
62
  uri = URI.parse(uri)
45
63
  unless %w(pryem pryems).include?(uri.scheme)
46
- abort "only pryem URIs are currently supported\n usage: pryem[s]://127.0.0.1:#{PryRemoteEm::DEF_BROKERPORT}"
64
+ abort "only pryem URIs are currently supported\n usage: pryem[s]://#{PryRemoteEm::DEFAULT_BROKER_HOST}:#{PryRemoteEm::DEFAULT_BROKER_PORT}"
47
65
  end
48
- uri.port = PryRemoteEm::DEF_BROKERPORT unless uri.port
66
+ uri.port = PryRemoteEm::DEFAULT_BROKER_PORT unless uri.port
49
67
 
50
68
  tried = 0
51
69
  auth_proc = proc do
52
70
  tried += 1
53
- user = uri.user || ($stdin.tty? ? Readline.readline("user: ") : raise("username is require for authentication"))
71
+ user = uri.user || ($stdin.tty? ? Readline.readline('user: ') : raise('username is require for authentication'))
54
72
  pass = if !uri.password.nil? && tried <= 1
55
73
  uri.password
56
74
  elsif $stdin.tty?
57
- HighLine.new.ask("#{user}'s password: ") { |q| q.echo = '*'}
75
+ HighLine.new.ask("#{user}'s password: ") { |q| q.echo = '*' }
58
76
  else
59
- raise "password is required to authenticate"
60
- end
77
+ raise 'password is required to authenticate'
78
+ end
61
79
  [user, pass]
62
80
  end
63
81
 
64
82
  EM.run do
65
- PryRemoteEm::Client.start(uri.host, uri.port, options.merge(:auth=>auth_proc, :tls=>uri.scheme=='pryems')) { |e| EM.stop }
83
+ client_options = options.merge(auth: auth_proc, tls: uri.scheme == 'pryems')
84
+ PryRemoteEm::Client.start(uri.host, uri.port, client_options) { EM.stop }
66
85
  end
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pry-remote-em/broker'
4
+ require 'optparse'
5
+
6
+ options = { tls: false }
7
+ OptionParser.new do |opts|
8
+ opts.on('-h', '--host HOST', 'host to bind broker server (same as PRYEMBROKER variable, default: "127.0.0.1")') do |host|
9
+ options[:host] = host
10
+ end
11
+
12
+ opts.on('-p', '--port PORT', 'port to bind broker server (same as PRYEMBROKERPORT variable, default: 6462)') do |port|
13
+ options[:port] = port
14
+ end
15
+
16
+ opts.on('-s', '--tls', 'use TLS for broker (default: false)') do
17
+ options[:tls] = true
18
+ end
19
+
20
+ opts.parse!(ARGV)
21
+ end
22
+
23
+
24
+ EM.run do
25
+ trap(:INT) { EM.stop }
26
+
27
+ PryRemoteEm::Broker.run options[:host], options[:port], tls: options[:tls], raise_if_port_in_use: true
28
+ end
@@ -1,29 +1,40 @@
1
1
  begin
2
2
  require 'openssl'
3
3
  rescue LoadError
4
- warn "OpenSSL support is not available"
4
+ warn 'OpenSSL support is not available'
5
5
  end
6
- require 'pry-remote-em/version'
7
- require 'pry-remote-em/proto'
8
- require 'eventmachine'
9
6
  require 'socket'
10
7
  require 'fiber'
11
8
  require 'uri'
9
+ require 'eventmachine'
10
+ require 'pry-remote-em/version'
11
+ require 'pry-remote-em/proto'
12
+ require 'pry-remote-em/server'
12
13
 
13
14
  module PryRemoteEm
14
- DEFHOST = 'localhost'
15
- DEFPORT = 6463
16
- DEF_BROKERPORT = DEFPORT - 1
17
- DEF_BROKERHOST = 'localhost'
18
- NEGOTIMER = 15
15
+ DEFAULT_SERVER_HOST = '127.0.0.1'
16
+ DEFAULT_SERVER_PORT = 6463
17
+ DEFAULT_BROKER_HOST = '127.0.0.1'
18
+ DEFAULT_BROKER_PORT = 6462
19
+
20
+ NEGOTIATION_TIMEOUT = 15
21
+ HEARTBEAT_SEND_INTERVAL = 15
22
+ HEARTBEAT_CHECK_INTERVAL = 20
23
+ RECONNECT_TO_BROKER_TIMEOUT = 3
24
+
25
+ MAXIMUM_ERRORS_IN_SANDBOX = 100
19
26
  end
20
27
 
21
28
 
22
29
  class Object
23
- def remote_pry_em(host = PryRemoteEm::DEFHOST, port = PryRemoteEm::DEFPORT, opts = {:tls => false}, &blk)
24
- opts = {:target => self}.merge(opts)
25
- PryRemoteEm::Server.run(opts[:target], host, port, opts, &blk)
30
+ def remote_pry_em(host = nil, port = nil, options = {}, &block)
31
+ host, options = nil, host if host.kind_of?(Hash) # Support for options hash as first argument instead of third
32
+
33
+ options = { target: self, host: host, port: port }.merge(options)
34
+ PryRemoteEm::Server.run(options, &block)
26
35
  end
36
+
37
+ alias pry_remote_em remote_pry_em # source of common confusing
27
38
  end
28
39
 
29
40
 
@@ -1,3 +1,4 @@
1
+ require 'logger'
1
2
  require 'socket'
2
3
  require 'pry-remote-em'
3
4
  require 'pry-remote-em/client/broker'
@@ -9,29 +10,20 @@ module PryRemoteEm
9
10
  attr_reader :listening, :host, :port
10
11
  alias :listening? :listening
11
12
 
12
- def run(host = ENV['PRYEMBROKER'] || DEF_BROKERHOST, port = ENV['PRYEMBROKERPORT'] || DEF_BROKERPORT, opts = {:tls => false})
13
+ def run(host = nil, port = nil, opts = {})
14
+ host ||= ENV['PRYEMBROKER'].nil? || ENV['PRYEMBROKER'].empty? ? DEFAULT_BROKER_HOST : ENV['PRYEMBROKER']
15
+ port ||= ENV['PRYEMBROKERPORT'].nil? || ENV['PRYEMBROKERPORT'].empty? ? DEFAULT_BROKER_PORT : ENV['PRYEMBROKERPORT']
16
+ port = port.to_i if port.kind_of?(String)
13
17
  raise "root permission required for port below 1024 (#{port})" if port < 1024 && Process.euid != 0
14
- @host = host
15
- @port = port
18
+ @host = host
19
+ @port = port
20
+ opts = opts.dup
16
21
  # Brokers cannot use SSL directly. If they do then when a proxy request to an SSL server is received
17
22
  # the client and server will not be able to negotiate a SSL session. The proxied traffic can be SSL
18
23
  # encrypted, but the SSL session will be between the client and the server.
19
- opts = opts.dup
20
24
  opts[:tls] = false
21
- @opts = opts
22
- begin
23
- EM.start_server(host, port, PryRemoteEm::Broker, opts) do |broker|
24
- end
25
- log.info("[pry-remote-em broker] listening on #{opts[:tls] ? 'pryems' : 'pryem'}://#{host}:#{port}")
26
- @listening = true
27
- rescue => e
28
- # EM 1.0.0.beta4's message tells us the port is in use; 0.12.10 just says, 'no acceptor'
29
- if (e.message.include?('port is in use') || e.message.include?('no acceptor'))
30
- # [pry-remote-em broker] a broker is already listening on #{host}:#{port}
31
- else
32
- raise e
33
- end
34
- end
25
+ @opts = opts
26
+ start_server(host, port, opts) unless @listening || ENV['PRYEMREMOTEBROKER'] || @opts[:remote_broker]
35
27
  client { |c| yield self } if block_given?
36
28
  end
37
29
 
@@ -40,9 +32,9 @@ module PryRemoteEm
40
32
  @waiting = nil
41
33
  @client = nil
42
34
  run(@host, @port, @opts) do
43
- PryRemoteEm.servers.each do |url, (sig, name)|
44
- next unless EM.get_sockname(sig)
45
- register(url, name)
35
+ PryRemoteEm.servers.each do |id, description|
36
+ next unless EM.get_sockname(description[:server])
37
+ register(id: description[:id], urls: description[:urls], name: description[:name], details: description[:details])
46
38
  end
47
39
  end
48
40
  end
@@ -60,31 +52,38 @@ module PryRemoteEm
60
52
  @servers ||= {}
61
53
  end
62
54
 
63
- def register(url, name = 'unknown')
64
- expand_url(url).each do |u|
65
- client { |c| c.send_register_server(u, name) }
66
- end
55
+ def register(description)
56
+ client { |c| c.send_register_server(description[:id], description[:urls], description[:name], description[:details]) }
67
57
  end
68
58
 
69
- def unregister(url)
70
- expand_url(url).each do |u|
71
- client { |c| c.send_unregister_server(u) }
72
- end
59
+ def unregister(id)
60
+ client { |c| c.send_unregister_server(id) }
61
+ end
62
+
63
+ def register_server(id, description)
64
+ servers[id] = description
65
+ watch_heartbeats(id)
66
+ log.info("[pry-remote-em broker] registered #{id} #{description.inspect}")
67
+ end
68
+
69
+ def update_server(server, description)
70
+ server.update(urls: description[:urls], name: description[:name])
71
+ server[:details].update(description[:details])
73
72
  end
74
73
 
75
- def expand_url(url)
76
- return Array(url) if (u = URI.parse(url)).host != '0.0.0.0'
77
- Socket.ip_address_list.select { |a| a.ipv4? }
78
- .map(&:ip_address).map{|i| u.clone.tap{|mu| mu.host = i } }
74
+ def unregister_server(id)
75
+ server = servers.delete(id) or return
76
+ log.warn("[pry-remote-em broker] unregister #{id} #{server.inspect}")
77
+ timer = timers.delete(id)
78
+ timer.cancel if timer
79
+ hbeats.delete(id)
79
80
  end
80
81
 
81
- def watch_heartbeats(url)
82
- return if timers[url]
83
- timers[url] = EM::PeriodicTimer.new(20) do
84
- if !hbeats[url] || (Time.new - hbeats[url]) > 20
85
- servers.delete(url)
86
- timers[url].cancel
87
- timers.delete(url)
82
+ def watch_heartbeats(id)
83
+ interval = ENV['PRYEMHBCHECK'].nil? || ENV['PRYEMHBCHECK'].empty? ? HEARTBEAT_CHECK_INTERVAL : ENV['PRYEMHBCHECK']
84
+ timers[id] ||= EM::PeriodicTimer.new(interval) do
85
+ if !hbeats[id] || (Time.new - hbeats[id]) > 20
86
+ unregister_server(id)
88
87
  end
89
88
  end
90
89
  end
@@ -101,10 +100,26 @@ module PryRemoteEm
101
100
  @connected
102
101
  end
103
102
 
104
- private
103
+ private
104
+
105
+ def start_server(host, port, opts)
106
+ EM.start_server(host, port, PryRemoteEm::Broker, opts)
107
+ log.info("[pry-remote-em broker] listening on #{opts[:tls] ? 'pryems' : 'pryem'}://#{host}:#{port}")
108
+ @listening = true
109
+ rescue => error
110
+ if error.message.include?('port is in use')
111
+ if opts[:raise_if_port_in_use]
112
+ raise
113
+ else
114
+ # A broker is already listening on this port, we can do nothing
115
+ end
116
+ else
117
+ raise
118
+ end
119
+ end
105
120
 
106
121
  def client(&blk)
107
- raise ArgumentError.new("A block is required") unless block_given?
122
+ raise ArgumentError.new('A block is required') unless block_given?
108
123
  if @client
109
124
  yield @client
110
125
  return
@@ -115,9 +130,9 @@ module PryRemoteEm
115
130
  else
116
131
  @waiting = [blk]
117
132
  EM.connect(host, port, Client::Broker, @opts) do |client|
118
- client.errback { |e| raise(e || "broker client error") }
133
+ client.errback { |e| raise(e || 'broker client error') }
119
134
  client.callback do
120
- @client = client
135
+ @client = client
121
136
  while (w = @waiting.shift)
122
137
  w.call(client)
123
138
  end
@@ -129,25 +144,25 @@ module PryRemoteEm
129
144
 
130
145
  include Proto
131
146
 
132
- def receive_server_list
147
+ def receive_server_reload_list
133
148
  send_server_list(Broker.servers)
134
149
  end
135
150
 
136
- def receive_register_server(url, name)
137
- url = URI.parse(url)
138
- url.host = peer_ip if ['0.0.0.0', 'localhost', '127.0.0.1'].include?(url.host)
139
- log.info("[pry-remote-em broker] registered #{url} - #{name.inspect}") unless Broker.servers[url] == name
140
- Broker.servers[url] = name
141
- Broker.hbeats[url] = Time.new
142
- Broker.watch_heartbeats(url)
143
- name
151
+ def receive_register_server(id, urls, name, details)
152
+ @ids.push(id)
153
+ description = { urls: urls, name: name, details: details }
154
+ Broker.hbeats[id] = Time.new
155
+ server = Broker.servers[id]
156
+ if server
157
+ Broker.update_server(server, description)
158
+ else
159
+ Broker.register_server(id, description)
160
+ end
144
161
  end
145
162
 
146
- def receive_unregister_server(url)
147
- url = URI.parse(url)
148
- url.host = peer_ip if ['0.0.0.0', 'localhost', '127.0.0.1'].include?(url.host)
149
- log.warn("[pry-remote-em broker] unregister #{url}")
150
- Broker.servers.delete(url)
163
+ def receive_unregister_server(id)
164
+ server = Broker.servers[id]
165
+ Broker.unregister_server(id) if server
151
166
  end
152
167
 
153
168
  def receive_proxy_connection(url)
@@ -156,8 +171,9 @@ module PryRemoteEm
156
171
  EM.connect(url.host, url.port, Client::Proxy, self)
157
172
  end
158
173
 
159
- def initialize(opts = {:tls => false}, &blk)
160
- @opts = opts
174
+ def initialize(opts = {}, &blk)
175
+ @opts = opts
176
+ @ids = []
161
177
  end
162
178
 
163
179
  def log
@@ -179,15 +195,16 @@ module PryRemoteEm
179
195
 
180
196
  def peer_ip
181
197
  return @peer_ip if @peer_ip
182
- return "" if get_peername.nil?
198
+ return '' if get_peername.nil?
183
199
  @peer_port, @peer_ip = Socket.unpack_sockaddr_in(get_peername)
200
+ @peer_ip = '127.0.0.1' if @peer_ip == '::1' # Little hack to avoid segmentation fault in EventMachine 1.2.0.1 while connecting to PryRemoteEm Server from localhost with IPv6 address
184
201
  @peer_ip
185
202
  end
186
203
 
187
204
  def peer_port
188
205
  return @peer_port if @peer_port
189
- return "" if get_peername.nil?
190
- @peer_port, @peer_ip = Socket.unpack_sockaddr_in(get_peername)
206
+ return '' if get_peername.nil?
207
+ peer_ip # Fills peer_port too
191
208
  @peer_port
192
209
  end
193
210
 
@@ -196,5 +213,10 @@ module PryRemoteEm
196
213
  send_server_list(Broker.servers)
197
214
  end
198
215
 
216
+ def unbind
217
+ @ids.each do |id|
218
+ Broker.unregister_server(id)
219
+ end
220
+ end
199
221
  end # module::Broker
200
222
  end # module::PryRemoteEm
@@ -1,24 +1,21 @@
1
1
  require 'uri'
2
2
  require 'pry-remote-em'
3
- begin
4
- require 'pry-remote-em/client/keyboard'
5
- rescue LoadError => e
6
- warn "[pry-remote-em] unable to load keyboard depenencies (termios); interactive shell commands disabled"
7
- end
8
- require "pry-remote-em/client/generic"
3
+ require 'pry-remote-em/client/keyboard'
4
+ require 'pry-remote-em/client/generic'
5
+ require 'pry-remote-em/client/interactive_menu'
9
6
  require 'pry'
10
- require "readline"
11
- require 'highline'
7
+ #require 'pry-coolline' rescue require 'readline'
12
8
 
13
9
  module PryRemoteEm
14
10
  module Client
15
11
  include EM::Deferrable
16
- include Client::Generic
12
+ include Generic
13
+ include InteractiveMenu
17
14
  include Pry::Helpers::BaseHelpers
18
15
 
19
16
  class << self
20
- def start(host = PryRemoteEm::DEFHOST, port = PryRemoteEM::DEFPORT, opts = {:tls => false})
21
- EM.connect(host || PryRemoteEm::DEFHOST, port || PryRemoteEm::DEFPORT, PryRemoteEm::Client, opts) do |c|
17
+ def start(host = nil, port = nil, opts = {})
18
+ EM.connect(host || PryRemoteEm::DEFAULT_SERVER_HOST, port || PryRemoteEm::DEFAULT_SERVER_PORT, PryRemoteEm::Client, opts) do |c|
22
19
  c.callback { yield if block_given? }
23
20
  c.errback do |e|
24
21
  Kernel.puts "[pry-remote-em] connection failed\n#{e}"
@@ -42,11 +39,17 @@ module PryRemoteEm
42
39
  end
43
40
 
44
41
  def post_init
45
- Readline.completion_proc = method(:auto_complete)
42
+ @input = if defined?(PryCoolline)
43
+ PryCoolline.make_coolline
44
+ else
45
+ Pry.history.load if Pry.config.history.should_load
46
+ Readline
47
+ end
48
+ @input.completion_proc = method(:auto_complete)
46
49
  end
47
50
 
48
51
  def ssl_handshake_completed
49
- log.info("[pry-remote-em] TLS connection established")
52
+ log.info('[pry-remote-em] TLS connection established')
50
53
  @opts[:tls] = true
51
54
  end
52
55
 
@@ -60,9 +63,7 @@ module PryRemoteEm
60
63
  reconnect(uri.host, uri.port)
61
64
  else
62
65
  @unbound = true
63
- log.info("[pry-remote-em] session terminated")
64
- # prior to 1.0.0.b4 error? returns true here even when it's not
65
- return succeed if Gem.loaded_specs["eventmachine"].version < Gem::Version.new("1.0.0.beta4")
66
+ log.info('[pry-remote-em] session terminated')
66
67
  error? ? fail : succeed
67
68
  end
68
69
  end
@@ -79,108 +80,19 @@ module PryRemoteEm
79
80
  log.info("\033[33m[pry-remote-em] no servers are registered with the broker\033[0m")
80
81
  Process.exit
81
82
  end
82
- choice, proxy = choose_server(list)
83
- return unless choice
84
- uri, name = choice[0], choice[1]
83
+ url, proxy = choose_server(list)
84
+ return unless url
85
+ uri = URI.parse(url)
85
86
  if proxy
86
87
  @opts[:tls] = uri.scheme == 'pryems'
87
88
  @negotiated = false
88
89
  @tls_started = false
89
- return send_proxy_connection(uri)
90
+ return send_proxy_connection(url)
90
91
  end
91
92
  @reconnect_to = uri
92
93
  close_connection
93
94
  end
94
95
 
95
- def choose_server(list)
96
- highline = HighLine.new
97
- proxy = false
98
- choice = nil
99
- nm_col_len = list.values.map(&:length).sort[-1] + 5
100
- ur_col_len = list.keys.map(&:length).sort[-1] + 5
101
- header = sprintf("| %-3s | %-#{nm_col_len}s | %-#{ur_col_len}s |", "", "name", "url")
102
- border = ("-" * header.length)
103
- table = [border, header, border]
104
- list = list.to_a.map{|url, name| [URI.parse(url), name]}
105
- list = filter_server_list(list)
106
- list = sort_server_list(list)
107
- list.each_with_index do |(url, name), idx|
108
- table << sprintf("| %-2d | %-#{nm_col_len}s | %-#{ur_col_len}s |", idx + 1, name, url)
109
- end
110
- table << border
111
- table = table.join("\n")
112
- Kernel.puts table
113
- while choice.nil?
114
- if proxy
115
- question = "(q) to quit; (r) to refresh (c) to connect\nproxy to: "
116
- else
117
- question = "(q) to quit; (r) to refresh (p) to proxy\nconnect to: "
118
- end
119
- if (choice = opts.delete(:proxy))
120
- proxy = true
121
- else
122
- choice = opts.delete(:connect) || highline.ask(question)
123
- proxy = false
124
- end
125
-
126
- return close_connection if ['q', 'quit', 'exit'].include?(choice.downcase)
127
- if ['r', 'reload', 'refresh'].include?(choice.downcase)
128
- send_server_list
129
- return nil
130
- end
131
- if ['c', 'connect'].include?(choice.downcase)
132
- proxy = false
133
- choice = nil
134
- next
135
- end
136
- if ['p', 'proxy'].include?(choice.downcase)
137
- proxy = true
138
- choice = nil
139
- next
140
- end
141
- choice = choice.to_i > 0 ?
142
- list[choice.to_i - 1] :
143
- list.find{|(url, name)| url.to_s == choice || name == choice }
144
- log.error("\033[31mserver not found\033[0m") unless choice
145
- end
146
- [choice, proxy]
147
- end
148
-
149
- def sort_server_list(list)
150
- type = opts[:sort] || :host
151
- case type
152
- when :name
153
- list.sort { |a,b| a[1] <=> b[1] }
154
- when :host
155
- list.sort { |a,b| a[0].host <=> b[0].host }
156
- when :ssl
157
- list.sort { |a,b| b[0].scheme <=> a[0].scheme }
158
- when :port
159
- list.sort { |a,b| a[0].port <=> b[0].port }
160
- else
161
- list.sort { |a,b| a[0].host <=> b[0].host }
162
- end
163
- end
164
-
165
- def filter_server_list(list)
166
- if opts[:filter_host]
167
- list = list.select { |url, name| url.host =~ opts[:filter_host] }
168
- end
169
- if opts[:filter_name]
170
- list = list.select { |url, name| name =~ opts[:filter_name] }
171
- end
172
- if opts.include?(:filter_ssl)
173
- list = opts[:filter_ssl] ?
174
- list.select{|url, name| url.scheme == 'pryems' } :
175
- list.select{|url, name| url.scheme == 'pryem' }
176
- end
177
- if list.empty?
178
- log.info("\033[33m[pry-remote-em] no registered servers match the given filter\033[0m")
179
- Process.exit
180
- end
181
- list
182
- end
183
-
184
96
  def receive_auth(a)
185
97
  return fail a if a.is_a?(String)
186
98
  return authenticate if a == false
@@ -204,11 +116,22 @@ module PryRemoteEm
204
116
  @keyboard.bufferio(true)
205
117
  @keyboard.close_connection
206
118
  end
119
+ if c == 255 || c == 127
120
+ Kernel.puts 'command not found'
121
+ end
122
+ end
123
+
124
+ # TODO detect if the old pager behavior of Pry is supported and use it
125
+ # through Pry.pager. If it's not then use the SimplePager.
126
+ def pager
127
+ pager_class = ENV['PRYEMNOPAGER'] ? Pry::Pager::NullPager : @opts[:pager] || Pry::Pager::SimplePager
128
+ @pager ||= pager_class.new(Pry::Output.new(Pry))
207
129
  end
208
130
 
209
131
  def receive_raw(r)
210
- # Pry::Helpers::BaseHelpers
211
- stagger_output(r, $stdout)
132
+ pager.write(r)
133
+ rescue Pry::Pager::StopPaging
134
+ warn '[pry-remote-em] stop paging is not implemented, use PRYEMNOPAGER environment variable to avoid paging at all'
212
135
  end
213
136
 
214
137
  def receive_unknown(j)
@@ -216,7 +139,7 @@ module PryRemoteEm
216
139
  end
217
140
 
218
141
  def authenticate
219
- return fail("[pry-remote-em] authentication required") unless @auth
142
+ return fail('[pry-remote-em] authentication required') unless @auth
220
143
  return fail("[pry-remote-em] can't authenticate before negotiation complete") unless @negotiated
221
144
  user, pass = @auth.call
222
145
  return fail("[pry-remote-em] expected #{@auth} to return a user and password") unless user && pass
@@ -224,6 +147,8 @@ module PryRemoteEm
224
147
  end # authenticate
225
148
 
226
149
  def auto_complete(word)
150
+ word = word.completed_word if defined?(Coolline) && word.kind_of?(Coolline)
151
+
227
152
  @waiting = Thread.current
228
153
  EM.next_tick { send_completion(word) }
229
154
  sleep
@@ -243,26 +168,37 @@ module PryRemoteEm
243
168
  readline(p)
244
169
  end
245
170
 
246
- def readline(prompt)
171
+ def readline(prompt = @last_prompt)
172
+ @last_prompt = prompt
247
173
  if @negotiated && !@unbound
248
- op = proc { Readline.readline(prompt, !prompt.nil?) }
249
- callback = proc do |l|
250
- if '!!' == l[0..1]
174
+ operation = proc do
175
+ thread = Thread.current
176
+ old_trap = Signal.trap(:INT) { thread.raise Interrupt }
177
+ begin
178
+ @input.readline(prompt)
179
+ rescue Interrupt
180
+ send_clear_buffer
181
+ puts
182
+ :ignore_me
183
+ ensure
184
+ Signal.trap(:INT, old_trap)
185
+ end
186
+ end
187
+
188
+ callback = proc do |l|
189
+ next if l == :ignore_me
190
+
191
+ add_to_history(l) unless l.nil? || l.empty?
192
+
193
+ if l.nil?
194
+ readline
195
+ elsif '^^' == l[0..1]
251
196
  send_msg_bcast(l[2..-1])
252
- elsif '!' == l[0]
197
+ elsif '^' == l[0]
253
198
  send_msg(l[1..-1])
254
199
  elsif '.' == l[0]
255
- if !Client.const_defined?(:Keyboard)
256
- Kernel.puts "\033[31minteractive shell commands are not supported without termios\033[0m"
257
- readline(prompt)
258
- else
259
- send_shell_cmd(l[1..-1])
260
- if Gem.loaded_specs["eventmachine"].version < Gem::Version.new("1.0.0.beta4")
261
- Kernel.puts "\033[1minteractive shell commands are not well supported when running on EventMachine prior to 1.0.0.beta4\033[0m"
262
- else
263
- @keyboard = EM.open_keyboard(Keyboard, self)
264
- end
265
- end
200
+ send_shell_cmd(l[1..-1])
201
+ @keyboard = EM.open_keyboard(Keyboard, self)
266
202
  elsif 'reset' == l.strip
267
203
  # TODO work with 'bundle exec pry-remote-em ...'
268
204
  # TODO work with 'ruby -I lib bin/pry-remote-em ...'
@@ -270,15 +206,24 @@ module PryRemoteEm
270
206
  exec("#{$0} #{ARGV.join(' ')}")
271
207
  else
272
208
  send_raw(l)
273
- end # "!!" == l[0..1]
209
+ end
274
210
  end
275
- EM.defer(op, callback)
211
+
212
+ EM.defer(operation, callback)
276
213
  end
277
214
  end # readline(prompt = @last_prompt)
278
215
 
216
+ def add_to_history(line)
217
+ if defined?(Readline) && @input == Readline
218
+ Readline::HISTORY.push(line)
219
+ end
220
+ # Nothing to do with Coolline, it just works
221
+ end
279
222
  end # module::Client
280
223
  end # module::PryRemoteEm
281
224
 
225
+ # TODO detect if the old pager behavior of Pry is supported and use it. If it's not
226
+ # then don't bother adding a pager accessor
282
227
  # Pry::Helpers::BaseHelpers#stagger_output expects Pry.pager to be defined
283
228
  class Pry
284
229
  class << self