pryx 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.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +52 -0
- data/bin/pry! +4 -0
- data/lib/break/pry/extensions.rb +56 -0
- data/lib/pry-byebug/WARN +4 -0
- data/lib/pry-byebug/base.rb +1 -0
- data/lib/pry-byebug/commands.rb +1 -0
- data/lib/pry-byebug/control_d_handler.rb +1 -0
- data/lib/pry-byebug/pry_ext.rb +1 -0
- data/lib/pry-byebug.rb +1 -0
- data/lib/pry-disasm/commands.rb +12 -0
- data/lib/pry-disasm/version.rb +5 -0
- data/lib/pry-disasm.rb +23 -0
- data/lib/pry-remote.rb +325 -0
- data/lib/pryx/ap_hack.rb +15 -0
- data/lib/pryx/break_hack.rb +2 -0
- data/lib/pryx/drip.wav +0 -0
- data/lib/pryx/looksee_hack.rb +34 -0
- data/lib/pryx/pry_hack.rb +164 -0
- data/lib/pryx/trap_backtrace.rb +7 -0
- data/lib/pryx/version.rb +5 -0
- data/lib/pryx.rb +9 -0
- data/lib/pryx_irb.rb +3 -0
- metadata +193 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1a334b6edbe6c01e52d776d88d29167fce2723de70139c15d60f951104f2c493
|
4
|
+
data.tar.gz: f9d13daa9cf6e8bc6f3f22769384575dae8a25eaa6cc132c15b72787fe0050d5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1ece992ef3f7271005f8c1c9e2487eb3639b221384303899bbfd0ee985e41e62c3a434ba524524057e94776e97fb10bd5de1a68340f48c0013f1c01486c51a21
|
7
|
+
data.tar.gz: 7d04d1c588433bb0eeb02972cb71ac1c2568e58e6230712e383a962e57b4c4df1d014d75da0edc08e1d68ee030aa3d82beb5d774ee79b1078778667670a56727
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2022 Billy.Zheng
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Pryx [](https://travis-ci.org/zw963/pryx) [](http://badge.fury.io/rb/pryx)
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Philosophy
|
6
|
+
|
7
|
+
TODO: Write philosophy
|
8
|
+
|
9
|
+
## Getting Started
|
10
|
+
|
11
|
+
Install via Rubygems
|
12
|
+
|
13
|
+
$ gem install pryx
|
14
|
+
|
15
|
+
OR ...
|
16
|
+
|
17
|
+
Add to your Gemfile
|
18
|
+
|
19
|
+
gem 'pryx'
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
TODO: Write usage instructions here
|
24
|
+
|
25
|
+
## Support
|
26
|
+
|
27
|
+
* MRI 1.9.3+
|
28
|
+
* Rubinius 2.2+
|
29
|
+
|
30
|
+
## Dependency
|
31
|
+
|
32
|
+
No known limit.
|
33
|
+
|
34
|
+
## History
|
35
|
+
|
36
|
+
See [CHANGELOG](https://github.com/zw963/pryx/blob/master/CHANGELOG) for details.
|
37
|
+
|
38
|
+
## Contributing
|
39
|
+
|
40
|
+
* [Bug reports](https://github.com/zw963/pryx/issues)
|
41
|
+
* [Source](https://github.com/zw963/pryx)
|
42
|
+
* Patches:
|
43
|
+
* Fork on Github.
|
44
|
+
* Run `gem install --dev pryx` or `bundle install`.
|
45
|
+
* Create your feature branch: `git checkout -b my-new-feature`.
|
46
|
+
* Commit your changes: `git commit -am 'Add some feature'`.
|
47
|
+
* Push to the branch: `git push origin my-new-feature`.
|
48
|
+
* Send a pull request :D.
|
49
|
+
|
50
|
+
## license
|
51
|
+
|
52
|
+
Released under the MIT license, See [LICENSE](https://github.com/zw963/pryx/blob/master/LICENSE) for details.
|
data/bin/pry!
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Break::Pry
|
4
|
+
module PryExtensions
|
5
|
+
attr_accessor :__break_session__
|
6
|
+
|
7
|
+
def initialize(options={})
|
8
|
+
super(options)
|
9
|
+
|
10
|
+
@__break_session__ = options[:__break_session__]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Pry.prepend Break::Pry::PryExtensions
|
16
|
+
|
17
|
+
begin
|
18
|
+
require 'pry-remote'
|
19
|
+
|
20
|
+
module Break::Pry
|
21
|
+
class << self
|
22
|
+
attr_accessor :current_remote_server
|
23
|
+
end
|
24
|
+
|
25
|
+
module PryRemoteServerExtensions
|
26
|
+
def initialize(*)
|
27
|
+
Break::Pry.current_remote_server&.teardown
|
28
|
+
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def run
|
33
|
+
return if Break::Pry.current_remote_server
|
34
|
+
|
35
|
+
Break::Pry.current_remote_server = self
|
36
|
+
|
37
|
+
setup
|
38
|
+
|
39
|
+
Pry.start @object, @options.merge(input: client.input_proxy, output: client.output)
|
40
|
+
end
|
41
|
+
|
42
|
+
def teardown
|
43
|
+
super
|
44
|
+
ensure
|
45
|
+
Break::Pry.current_remote_server = nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Hack for break works with pry_remote.
|
51
|
+
# More details, see: https://github.com/gsamokovarov/break/issues/9
|
52
|
+
|
53
|
+
# PryRemote::Server.prepend Break::Pry::PryRemoteServerExtensions
|
54
|
+
rescue LoadError
|
55
|
+
# Do nothing if we cannot require pry-remote.
|
56
|
+
end
|
data/lib/pry-byebug/WARN
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# dummy
|
@@ -0,0 +1 @@
|
|
1
|
+
# dummy
|
@@ -0,0 +1 @@
|
|
1
|
+
# dummy
|
@@ -0,0 +1 @@
|
|
1
|
+
# dummy
|
data/lib/pry-byebug.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# dummy
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Pry::Commands.create_command 'disasm' do
|
4
|
+
description 'Pry plugin that displays YARV bytecode for a method or expression. '
|
5
|
+
command_options argument_required: true
|
6
|
+
group 'Context'
|
7
|
+
|
8
|
+
def process
|
9
|
+
expr = eval(arg_string)
|
10
|
+
PryDisasm.process(expr)
|
11
|
+
end
|
12
|
+
end
|
data/lib/pry-disasm.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pry'
|
4
|
+
require 'pry-disasm/commands'
|
5
|
+
require 'pry-disasm/version'
|
6
|
+
|
7
|
+
class PryDisasm
|
8
|
+
def self.process(expr)
|
9
|
+
str = RubyVM::InstructionSequence.disasm(expr)
|
10
|
+
|
11
|
+
lines = str.split("\n")
|
12
|
+
lines[0].gsub!(/=+/) { |s| "\033[0;32m#{s}\033[0m" }
|
13
|
+
lines[0].gsub!(/<(.*?)@(.*?)>/) { "<\033[0;33m#{$1}\033[0m@\033[0;33m#{$2}\033[0m>" }
|
14
|
+
|
15
|
+
(1..lines.length).each do |i|
|
16
|
+
lines[i] = "\033[0;35m#{lines[i]}\033[0m"
|
17
|
+
lines[i].gsub!(/^(.*?)(\s+)(.*?)(\s+)/) { "#{$1}#{$2}\033[0;36m#{$3}\033[0m#{$4}" }
|
18
|
+
lines[i].gsub!(/<(.*?):(.*?)>/) { "<\033[0;34m#{$1}\033[0m#:#{$2}>" }
|
19
|
+
end
|
20
|
+
|
21
|
+
puts lines
|
22
|
+
end
|
23
|
+
end
|
data/lib/pry-remote.rb
ADDED
@@ -0,0 +1,325 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require 'drb'
|
3
|
+
require 'readline'
|
4
|
+
require 'open3'
|
5
|
+
|
6
|
+
module PryRemote
|
7
|
+
DefaultHost = "127.0.0.1"
|
8
|
+
DefaultPort = 9876
|
9
|
+
|
10
|
+
# A class to represent an input object created from DRb. This is used because
|
11
|
+
# Pry checks for arity to know if a prompt should be passed to the object.
|
12
|
+
#
|
13
|
+
# @attr [#readline] input Object to proxy
|
14
|
+
InputProxy = Struct.new :input do
|
15
|
+
# Reads a line from the input
|
16
|
+
def readline(prompt)
|
17
|
+
case readline_arity
|
18
|
+
when 1 then input.readline(prompt)
|
19
|
+
else input.readline
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def completion_proc=(val)
|
24
|
+
input.completion_proc = val
|
25
|
+
end
|
26
|
+
|
27
|
+
def readline_arity
|
28
|
+
input.method_missing(:method, :readline).arity
|
29
|
+
rescue NameError
|
30
|
+
0
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Class used to wrap inputs so that they can be sent through DRb.
|
35
|
+
#
|
36
|
+
# This is to ensure the input is used locally and not reconstructed on the
|
37
|
+
# server by DRb.
|
38
|
+
class IOUndumpedProxy
|
39
|
+
include DRb::DRbUndumped
|
40
|
+
|
41
|
+
def initialize(obj)
|
42
|
+
@obj = obj
|
43
|
+
end
|
44
|
+
|
45
|
+
def completion_proc=(val)
|
46
|
+
if @obj.respond_to? :completion_proc=
|
47
|
+
@obj.completion_proc = val
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def completion_proc
|
52
|
+
@obj.completion_proc if @obj.respond_to? :completion_proc
|
53
|
+
end
|
54
|
+
|
55
|
+
def readline(prompt)
|
56
|
+
if Readline == @obj
|
57
|
+
@obj.readline(prompt, true)
|
58
|
+
elsif @obj.method(:readline).arity == 1
|
59
|
+
@obj.readline(prompt)
|
60
|
+
else
|
61
|
+
$stdout.print prompt
|
62
|
+
@obj.readline
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def puts(*lines)
|
67
|
+
@obj.puts(*lines)
|
68
|
+
end
|
69
|
+
|
70
|
+
def print(*objs)
|
71
|
+
@obj.print(*objs)
|
72
|
+
end
|
73
|
+
|
74
|
+
def printf(*args)
|
75
|
+
@obj.printf(*args)
|
76
|
+
end
|
77
|
+
|
78
|
+
def write(data)
|
79
|
+
@obj.write data
|
80
|
+
end
|
81
|
+
|
82
|
+
def <<(data)
|
83
|
+
@obj << data
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
# Some versions of Pry expect $stdout or its output objects to respond to
|
88
|
+
# this message.
|
89
|
+
def tty?
|
90
|
+
false
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Ensure that system (shell command) output is redirected for remote session.
|
95
|
+
System = proc do |output, cmd, _|
|
96
|
+
status = nil
|
97
|
+
Open3.popen3 cmd do |stdin, stdout, stderr, wait_thr|
|
98
|
+
stdin.close # Send EOF to the process
|
99
|
+
|
100
|
+
until stdout.eof? and stderr.eof?
|
101
|
+
if res = IO.select([stdout, stderr])
|
102
|
+
res[0].each do |io|
|
103
|
+
next if io.eof?
|
104
|
+
output.write io.read_nonblock(1024)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
status = wait_thr.value
|
110
|
+
end
|
111
|
+
|
112
|
+
unless status.success?
|
113
|
+
output.puts "Error while executing command: #{cmd}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# A client is used to retrieve information from the client program.
|
118
|
+
Client = Struct.new :input, :output, :thread, :stdout, :stderr do
|
119
|
+
# Waits until both an input and output are set
|
120
|
+
def wait
|
121
|
+
sleep 0.01 until input and output and thread
|
122
|
+
end
|
123
|
+
|
124
|
+
# Tells the client the session is terminated
|
125
|
+
def kill
|
126
|
+
thread.run
|
127
|
+
end
|
128
|
+
|
129
|
+
# @return [InputProxy] Proxy for the input
|
130
|
+
def input_proxy
|
131
|
+
InputProxy.new input
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class Server
|
136
|
+
def self.run(object, host = DefaultHost, port = DefaultPort, options = {})
|
137
|
+
new(object, host, port, options).run
|
138
|
+
end
|
139
|
+
|
140
|
+
def initialize(object, host = DefaultHost, port = DefaultPort, options = {})
|
141
|
+
@host = host
|
142
|
+
@port = port
|
143
|
+
|
144
|
+
@object = object
|
145
|
+
@options = options
|
146
|
+
|
147
|
+
@client = PryRemote::Client.new
|
148
|
+
DRb.start_service uri, @client
|
149
|
+
|
150
|
+
puts "[pry-remote] Waiting for client on #{uri}"
|
151
|
+
@client.wait
|
152
|
+
|
153
|
+
puts "[pry-remote] Client received, starting remote session"
|
154
|
+
end
|
155
|
+
|
156
|
+
# Code that has to be called for Pry-remote to work properly
|
157
|
+
def setup
|
158
|
+
# If client passed stdout and stderr, redirect actual messages there.
|
159
|
+
@old_stdout, $stdout = if @client.stdout
|
160
|
+
[$stdout, @client.stdout]
|
161
|
+
else
|
162
|
+
[$stdout, $stdout]
|
163
|
+
end
|
164
|
+
|
165
|
+
@old_stderr, $stderr = if @client.stderr
|
166
|
+
[$stderr, @client.stderr]
|
167
|
+
else
|
168
|
+
[$stderr, $stderr]
|
169
|
+
end
|
170
|
+
|
171
|
+
# Before Pry starts, save the pager config.
|
172
|
+
# We want to disable this because the pager won't do anything useful in
|
173
|
+
# this case (it will run on the server).
|
174
|
+
Pry.config.pager, @old_pager = false, Pry.config.pager
|
175
|
+
|
176
|
+
# As above, but for system config
|
177
|
+
Pry.config.system, @old_system = PryRemote::System, Pry.config.system
|
178
|
+
end
|
179
|
+
|
180
|
+
# Code that has to be called after setup to return to the initial state
|
181
|
+
def teardown
|
182
|
+
# Reset output streams
|
183
|
+
$stdout = @old_stdout
|
184
|
+
$stderr = @old_stderr
|
185
|
+
|
186
|
+
# Reset config
|
187
|
+
Pry.config.pager = @old_pager
|
188
|
+
|
189
|
+
# Reset sysem
|
190
|
+
Pry.config.system = @old_system
|
191
|
+
|
192
|
+
puts "[pry-remote] Remote session terminated"
|
193
|
+
|
194
|
+
begin
|
195
|
+
@client.kill
|
196
|
+
rescue DRb::DRbConnError
|
197
|
+
puts "[pry-remote] Continuing to stop service"
|
198
|
+
ensure
|
199
|
+
puts "[pry-remote] Ensure stop service"
|
200
|
+
DRb.stop_service
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Actually runs pry-remote
|
205
|
+
def run
|
206
|
+
setup
|
207
|
+
|
208
|
+
Pry.start(@object, @options.merge(:input => client.input_proxy, :output => client.output))
|
209
|
+
ensure
|
210
|
+
teardown
|
211
|
+
end
|
212
|
+
|
213
|
+
# @return Object to enter into
|
214
|
+
attr_reader :object
|
215
|
+
|
216
|
+
# @return [PryServer::Client] Client connecting to the pry-remote server
|
217
|
+
attr_reader :client
|
218
|
+
|
219
|
+
# @return [String] Host of the server
|
220
|
+
attr_reader :host
|
221
|
+
|
222
|
+
# @return [Integer] Port of the server
|
223
|
+
attr_reader :port
|
224
|
+
|
225
|
+
# @return [String] URI for DRb
|
226
|
+
def uri
|
227
|
+
"druby://#{host}:#{port}"
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
# Parses arguments and allows to start the client.
|
232
|
+
class CLI
|
233
|
+
def initialize(args = ARGV)
|
234
|
+
params = Pry::Slop.parse args, :help => true do
|
235
|
+
banner "#$PROGRAM_NAME [OPTIONS]"
|
236
|
+
|
237
|
+
on :s, :server=, "Host of the server (#{DefaultHost})", :argument => :optional,
|
238
|
+
:default => DefaultHost
|
239
|
+
on :p, :port=, "Port of the server (#{DefaultPort})", :argument => :optional,
|
240
|
+
:as => Integer, :default => DefaultPort
|
241
|
+
on :w, :wait, "Wait for the pry server to come up",
|
242
|
+
:default => false
|
243
|
+
on :c, :capture, "Captures $stdout and $stderr from the server (true)",
|
244
|
+
:default => true
|
245
|
+
on :f, "Disables loading of .pryrc and its plugins, requires, and command history "
|
246
|
+
end
|
247
|
+
|
248
|
+
exit if params.help?
|
249
|
+
|
250
|
+
@host = params[:server]
|
251
|
+
@port = params[:port]
|
252
|
+
|
253
|
+
@wait = params[:wait]
|
254
|
+
@capture = params[:capture]
|
255
|
+
|
256
|
+
Pry.initial_session_setup unless params[:f]
|
257
|
+
end
|
258
|
+
|
259
|
+
# @return [String] Host of the server
|
260
|
+
attr_reader :host
|
261
|
+
|
262
|
+
# @return [Integer] Port of the server
|
263
|
+
attr_reader :port
|
264
|
+
|
265
|
+
# @return [String] URI for DRb
|
266
|
+
def uri
|
267
|
+
"druby://#{host}:#{port}"
|
268
|
+
end
|
269
|
+
|
270
|
+
attr_reader :wait
|
271
|
+
attr_reader :capture
|
272
|
+
alias wait? wait
|
273
|
+
alias capture? capture
|
274
|
+
|
275
|
+
# Connects to the server
|
276
|
+
#
|
277
|
+
# @param [IO] input Object holding input for pry-remote
|
278
|
+
# @param [IO] output Object pry-debug will send its output to
|
279
|
+
def run(input = Pry.config.input, output = Pry.config.output)
|
280
|
+
local_ip = UDPSocket.open {|s| s.connect(@host, 1); s.addr.last}
|
281
|
+
DRb.start_service "druby://#{local_ip}:0"
|
282
|
+
client = DRbObject.new(nil, uri)
|
283
|
+
|
284
|
+
input = IOUndumpedProxy.new(input)
|
285
|
+
output = IOUndumpedProxy.new(output)
|
286
|
+
|
287
|
+
begin
|
288
|
+
client.input = input
|
289
|
+
client.output = output
|
290
|
+
rescue DRb::DRbConnError => ex
|
291
|
+
if wait?
|
292
|
+
sleep 1
|
293
|
+
retry
|
294
|
+
else
|
295
|
+
raise ex
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
if capture?
|
300
|
+
client.stdout = $stdout
|
301
|
+
client.stderr = $stderr
|
302
|
+
end
|
303
|
+
|
304
|
+
client.thread = Thread.current
|
305
|
+
|
306
|
+
sleep
|
307
|
+
DRb.stop_service
|
308
|
+
end
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
class Object
|
313
|
+
# Starts a remote Pry session
|
314
|
+
#
|
315
|
+
# @param [String] host Host of the server
|
316
|
+
# @param [Integer] port Port of the server
|
317
|
+
# @param [Hash] options Options to be passed to Pry.start
|
318
|
+
def remote_pry(host = PryRemote::DefaultHost, port = PryRemote::DefaultPort, options = {})
|
319
|
+
PryRemote::Server.new(self, host, port, options).run
|
320
|
+
end
|
321
|
+
|
322
|
+
# a handy alias as many people may think the method is named after the gem
|
323
|
+
# (pry-remote)
|
324
|
+
alias pry_remote remote_pry
|
325
|
+
end
|
data/lib/pryx/ap_hack.rb
ADDED
data/lib/pryx/drip.wav
ADDED
Binary file
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# ls1 支持的参数有:
|
2
|
+
# - String 或 Regexp,包含字符串或匹配正则过滤.
|
3
|
+
# - :nopublic :noprotected, :noprivate, :noundefined, :nooverridden 显示指定类型方法.
|
4
|
+
# 颜色方案
|
5
|
+
# 模块 白色 37
|
6
|
+
# 公开方法 绿色 32
|
7
|
+
# 保护方法 黄色 33
|
8
|
+
# 私有方法 红色 31
|
9
|
+
# 取消定义的方法 蓝色 34
|
10
|
+
# 被覆写的方法 灰色 30
|
11
|
+
|
12
|
+
module Kernel
|
13
|
+
def load_looksee
|
14
|
+
case RbConfig::CONFIG['ruby_version']
|
15
|
+
when '1.9.0'...'2.1.0'
|
16
|
+
require 'old_looksee'
|
17
|
+
when '2.1.0'...'3.2.0'
|
18
|
+
require 'looksee'
|
19
|
+
end
|
20
|
+
Looksee.rename :ls_looksee
|
21
|
+
|
22
|
+
Looksee.editor = '.emacsclient +%l %f' # e.g. [].ls1.edit :to_set
|
23
|
+
end
|
24
|
+
|
25
|
+
def ls1(*args)
|
26
|
+
load_looksee unless defined? Looksee
|
27
|
+
Looksee[self, *args, :noprivate]
|
28
|
+
end
|
29
|
+
|
30
|
+
def ls2(*args)
|
31
|
+
load_looksee unless defined? Looksee
|
32
|
+
Looksee[self, *args]
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
# 注意如果开启 pry-stack_explorer, 就不要使用 debugger, 因为进入新的上下文后, pry-stack_explorer 将失效.
|
2
|
+
|
3
|
+
require 'binding_of_caller'
|
4
|
+
|
5
|
+
class Binding
|
6
|
+
def _pry(host=nil, port=nil, options={})
|
7
|
+
if host
|
8
|
+
require 'pry-remote'
|
9
|
+
else
|
10
|
+
require 'pry'
|
11
|
+
end
|
12
|
+
require 'pryx/ap_hack'
|
13
|
+
require 'pryx/break_hack'
|
14
|
+
|
15
|
+
Pry::Commands.block_command 'cc', 'Continue, but stop in pry! breakpoint' do
|
16
|
+
Pry.instance_variable_set(:@initial_session, true)
|
17
|
+
ENV['Pry_was_started'] = nil
|
18
|
+
throw(:breakout)
|
19
|
+
end
|
20
|
+
|
21
|
+
if host
|
22
|
+
notify_send('loading remote pry ...')
|
23
|
+
# remote_pry(host, port, options) if Pry.initial_session?
|
24
|
+
remote_pry(host, port, options)
|
25
|
+
else
|
26
|
+
warn '[1m[33mloading pry ...[0m'
|
27
|
+
self.pry
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def _irb(_host=nil, _port=nil, _options={})
|
32
|
+
warn '[1m[33mloading irb ...[0m'
|
33
|
+
|
34
|
+
self.irb
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module Kernel
|
39
|
+
# 运行 pry! 会被拦截, 且只会被拦截一次.
|
40
|
+
def pry!(caller=2, remote: nil, port: 9876)
|
41
|
+
return unless ENV['Pry_was_started'].nil?
|
42
|
+
|
43
|
+
ENV['Pry_was_started'] = 'true'
|
44
|
+
|
45
|
+
if background?
|
46
|
+
remote = '0.0.0.0'
|
47
|
+
port = 9876
|
48
|
+
end
|
49
|
+
|
50
|
+
pry3(caller, remote:, port:)
|
51
|
+
|
52
|
+
# 这里如果有代码, 将会让 pry! 进入这个方法, 因此保持为空.
|
53
|
+
end
|
54
|
+
|
55
|
+
# 注意:pryr 总是会被拦截。
|
56
|
+
def pryr
|
57
|
+
pry3(caller = 2, remote: '0.0.0.0', port: 9876)
|
58
|
+
end
|
59
|
+
|
60
|
+
# 在 pry! 之前如果输入这个,会让下次执行的 pry! 被拦截一次, 而不管之前是否有执行过 pry!
|
61
|
+
def repry!
|
62
|
+
ENV['Pry_was_started'] = nil
|
63
|
+
end
|
64
|
+
|
65
|
+
# 和 pry! 的差别就是,pry? 使用 pry-state 插件输出当前 context 的很多变量内容。
|
66
|
+
# 注意:不需要总是开启 pry-state,因为有时候会输出太多内容,造成刷屏。
|
67
|
+
def pry?(caller=2, remote: nil, port: 9876)
|
68
|
+
return unless ENV['Pry_was_started'].nil?
|
69
|
+
|
70
|
+
require 'pry-state'
|
71
|
+
ENV['Pry_was_started'] = 'true'
|
72
|
+
|
73
|
+
pry3(caller, remote:, port:)
|
74
|
+
|
75
|
+
# 这里如果有代码, 将会让 pry! 进入这个方法, 因此保持为空.
|
76
|
+
end
|
77
|
+
|
78
|
+
# 等价于默认的 binding.pry, 会反复被拦截。
|
79
|
+
# 起成 pry3 这个名字,也是为了方便直接使用。
|
80
|
+
def pry3(caller=1, remote: nil, port: 9876)
|
81
|
+
binding.of_caller(caller)._pry(remote, port)
|
82
|
+
end
|
83
|
+
|
84
|
+
def pry1
|
85
|
+
ENV['Pry2_should_start'] = 'true'
|
86
|
+
end
|
87
|
+
|
88
|
+
# 1. 单独运行 pry2, 永远不会被拦截,
|
89
|
+
# 2. 如果之前运行过 pry1, 此时 pry2 将被拦截, 且只会被拦截一次.
|
90
|
+
|
91
|
+
def pry2(caller=1, remote: nil, port: 9876)
|
92
|
+
if ENV['Pry2_should_start'] == 'true'
|
93
|
+
# 首先恢复 Pry2_is_start 为未启动, 避免稍后的 pry2 再次被拦截.
|
94
|
+
ENV['Pry2_should_start'] = nil
|
95
|
+
binding.of_caller(caller)._pry(remote, port)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def reirb!
|
100
|
+
ENV['IRB_was_started'] = nil
|
101
|
+
end
|
102
|
+
|
103
|
+
def irb!
|
104
|
+
return unless ENV['IRB_was_started'].nil?
|
105
|
+
|
106
|
+
ENV['IRB_was_started'] = 'true'
|
107
|
+
|
108
|
+
binding.of_caller(1)._irb
|
109
|
+
end
|
110
|
+
|
111
|
+
def irb1
|
112
|
+
ENV['IRB2_should_start'] = 'true'
|
113
|
+
end
|
114
|
+
|
115
|
+
def irb2(caller=1, remote: nil, port: 9876)
|
116
|
+
if ENV['IRB2_should_start'] == 'true'
|
117
|
+
# 首先恢复 Pry2_is_start 为未启动, 避免稍后的 pry2 再次被拦截.
|
118
|
+
ENV['IRB2_should_start'] = nil
|
119
|
+
binding.of_caller(caller)._irb
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
# 如果是前台进程,则这个进程的组ID(pgid)一定会等于当前 terminal 的gid (tpgid)
|
124
|
+
# 否则,如果不等,那么就是后台进程。
|
125
|
+
# system("ps -e -o pid,pgid,tpgid |grep '^\s*#{pid}' |awk '$2==$3 {exit 1}'")
|
126
|
+
# system("\\cat /proc/#{pid}/stat |awk '$5==$8 {exit 1}'")
|
127
|
+
def background?(pid=$$)
|
128
|
+
# 考虑是否需要验证
|
129
|
+
ary = File.read("/proc/#{pid}/stat").split(' ').reverse
|
130
|
+
# 执行 reverse 再处理,是因为要考虑文件名包含空格因素。例如:‘hello) (world’
|
131
|
+
(ary[46] != ary[48]) && !$stdout.tty?
|
132
|
+
end
|
133
|
+
|
134
|
+
def foreground?(pid=$$)
|
135
|
+
not background?(pid)
|
136
|
+
end
|
137
|
+
|
138
|
+
def notify_send(msg)
|
139
|
+
system("notify-send \"#{msg}\"") if system 'which notify-send &>/dev/null'
|
140
|
+
|
141
|
+
system('aplay "#{__dir__}/drip.wav" &>/dev/null') if system 'which aplay &>/dev/null'
|
142
|
+
warn "[1m[33m#{msg}[0m"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Hack roda, 在每一次发送请求之前,总是设定 ENV['Pry_was_started'] to nil.
|
147
|
+
# 这可以确保,pry! 总是会被拦截,但是仅仅只会被拦截一次。
|
148
|
+
begin
|
149
|
+
require 'roda'
|
150
|
+
class PryHackRodaMiddleware
|
151
|
+
attr_reader :app
|
152
|
+
|
153
|
+
def initialize(app)
|
154
|
+
@app = app
|
155
|
+
end
|
156
|
+
|
157
|
+
def call(env)
|
158
|
+
ENV['Pry_was_started'] = nil
|
159
|
+
@app.call(env)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
Roda.use PryHackRodaMiddleware
|
163
|
+
rescue LoadError
|
164
|
+
end
|
data/lib/pryx/version.rb
ADDED
data/lib/pryx.rb
ADDED
data/lib/pryx_irb.rb
ADDED
metadata
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pryx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Billy.Zheng(zw963)
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-04-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pry
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.14'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.14'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry-power_assert
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.0.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.0.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry-doc
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: looksee
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '4.4'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '4.4'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: break
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.30'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.30'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: awesome_print
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.9'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.9'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: binding_of_caller
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rake
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: ritual
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0.4'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0.4'
|
139
|
+
description: ''
|
140
|
+
email:
|
141
|
+
- vil963@gmail.com
|
142
|
+
executables:
|
143
|
+
- pry!
|
144
|
+
extensions: []
|
145
|
+
extra_rdoc_files: []
|
146
|
+
files:
|
147
|
+
- LICENSE
|
148
|
+
- README.md
|
149
|
+
- bin/pry!
|
150
|
+
- lib/break/pry/extensions.rb
|
151
|
+
- lib/pry-byebug.rb
|
152
|
+
- lib/pry-byebug/WARN
|
153
|
+
- lib/pry-byebug/base.rb
|
154
|
+
- lib/pry-byebug/commands.rb
|
155
|
+
- lib/pry-byebug/control_d_handler.rb
|
156
|
+
- lib/pry-byebug/pry_ext.rb
|
157
|
+
- lib/pry-disasm.rb
|
158
|
+
- lib/pry-disasm/commands.rb
|
159
|
+
- lib/pry-disasm/version.rb
|
160
|
+
- lib/pry-remote.rb
|
161
|
+
- lib/pryx.rb
|
162
|
+
- lib/pryx/ap_hack.rb
|
163
|
+
- lib/pryx/break_hack.rb
|
164
|
+
- lib/pryx/drip.wav
|
165
|
+
- lib/pryx/looksee_hack.rb
|
166
|
+
- lib/pryx/pry_hack.rb
|
167
|
+
- lib/pryx/trap_backtrace.rb
|
168
|
+
- lib/pryx/version.rb
|
169
|
+
- lib/pryx_irb.rb
|
170
|
+
homepage: http://github.com/zw963/pryx
|
171
|
+
licenses:
|
172
|
+
- MIT
|
173
|
+
metadata: {}
|
174
|
+
post_install_message:
|
175
|
+
rdoc_options: []
|
176
|
+
require_paths:
|
177
|
+
- lib
|
178
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
179
|
+
requirements:
|
180
|
+
- - ">="
|
181
|
+
- !ruby/object:Gem::Version
|
182
|
+
version: 2.2.2
|
183
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
requirements: []
|
189
|
+
rubygems_version: 3.3.3
|
190
|
+
signing_key:
|
191
|
+
specification_version: 4
|
192
|
+
summary: ''
|
193
|
+
test_files: []
|