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 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 [![Build Status](https://travis-ci.org/zw963/pryx.svg?branch=master)](https://travis-ci.org/zw963/pryx) [![Gem Version](https://badge.fury.io/rb/pryx.svg)](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,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pry-remote'
4
+ PryRemote::CLI.new.run
@@ -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
@@ -0,0 +1,4 @@
1
+ 这个文件夹存在的目的,是作为一个 dummy pry-byebug, 并且,我在 pry_hack 中,
2
+ 设定总是优先 require 这个 pry-byebug,而不是项目中的 pry-byebug.
3
+
4
+ 最终的目的是,消除项目中 pry-byebug 对当前全局版本的 pry 的影响。
@@ -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
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class PryDisasm
4
+ VERSION = '1.0.0'
5
+ 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
@@ -0,0 +1,15 @@
1
+ require 'awesome_print'
2
+
3
+ AwesomePrint.defaults = {
4
+ index: false
5
+ }
6
+
7
+ if defined? AwesomePrint
8
+ if defined? Pry
9
+ require 'pry'
10
+ AwesomePrint.pry!
11
+ else
12
+ require 'irb'
13
+ AwesomePrint.irb!
14
+ end
15
+ end
@@ -0,0 +1,2 @@
1
+ require 'break'
2
+ load "#{__dir__}/../break/pry/extensions.rb"
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 'loading pry ...'
27
+ self.pry
28
+ end
29
+ end
30
+
31
+ def _irb(_host=nil, _port=nil, _options={})
32
+ warn 'loading irb ...'
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 "#{msg}"
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
@@ -0,0 +1,7 @@
1
+ trap(:QUIT) {
2
+ t = Thread.list.first
3
+ puts '#' * 90
4
+ p t
5
+ puts t.backtrace
6
+ puts '#' * 90
7
+ }
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Pryx
4
+ VERSION = '0.1.0'
5
+ end
data/lib/pryx.rb ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pryx/version'
4
+ require 'pryx/trap_backtrace'
5
+ require 'pryx/looksee_hack'
6
+ require 'pryx/pry_hack'
7
+
8
+ module Pryx
9
+ end
data/lib/pryx_irb.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'pryx/ap_hack'
2
+ require 'pryx/break_hack'
3
+ require 'pryx'
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: []