pry-shell 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +21 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +92 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +12 -0
- data/bin/console +16 -0
- data/bin/setup +8 -0
- data/exe/pry-shell +7 -0
- data/lib/pry/shell.rb +60 -0
- data/lib/pry/shell/cli.rb +59 -0
- data/lib/pry/shell/client.rb +47 -0
- data/lib/pry/shell/command.rb +22 -0
- data/lib/pry/shell/io/base.rb +28 -0
- data/lib/pry/shell/io/input.rb +19 -0
- data/lib/pry/shell/io/output.rb +40 -0
- data/lib/pry/shell/logger.rb +35 -0
- data/lib/pry/shell/patches/object.rb +15 -0
- data/lib/pry/shell/patches/repl.rb +46 -0
- data/lib/pry/shell/registry.rb +51 -0
- data/lib/pry/shell/server.rb +29 -0
- data/lib/pry/shell/session.rb +62 -0
- data/lib/pry/shell/ui.rb +26 -0
- data/lib/pry/shell/ui/about.rb +19 -0
- data/lib/pry/shell/ui/base.rb +73 -0
- data/lib/pry/shell/ui/list.rb +48 -0
- data/lib/pry/shell/ui/menu.rb +33 -0
- data/lib/pry/shell/ui/session.rb +20 -0
- data/lib/pry/shell/version.rb +7 -0
- data/pry-shell.gemspec +32 -0
- metadata +120 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: dd9174cd55c1ae7d73d49eca821fa5fedc1b39547c2cfad9437504694c5cca81
|
4
|
+
data.tar.gz: a57cda5282d83b3344277183b1cc3ed2893c413f6d0c18c0f36bf3649c9ef276
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: adfcbfe796953dccdb68c366722b82f0d8ba5115e7431f7583079c47774006ac88829d2bd8a3cda8a13b53ed0aa6aa50798d88e98bbaa9154c63c0ffe4603f8f
|
7
|
+
data.tar.gz: b1d14c0e9f591f955471979b1d96716021bded61885efb33cf3cb46e1d23346c3f779867366eb42bb3b5ae2b2281cd8c712df7546759ce5bd650dba8e2326dff
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.5
|
3
|
+
|
4
|
+
Style/Documentation:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
Style/FrozenStringLiteralComment:
|
8
|
+
Exclude:
|
9
|
+
- bin/**/*
|
10
|
+
- exe/**/*
|
11
|
+
|
12
|
+
Style/StringLiterals:
|
13
|
+
Enabled: true
|
14
|
+
EnforcedStyle: double_quotes
|
15
|
+
|
16
|
+
Style/StringLiteralsInInterpolation:
|
17
|
+
Enabled: true
|
18
|
+
EnforcedStyle: double_quotes
|
19
|
+
|
20
|
+
Layout/LineLength:
|
21
|
+
Max: 120
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
pry-shell (0.1.0)
|
5
|
+
pry (~> 0.13.0)
|
6
|
+
tty-markdown
|
7
|
+
tty-prompt
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
ast (2.4.2)
|
13
|
+
coderay (1.1.3)
|
14
|
+
diff-lcs (1.4.4)
|
15
|
+
kramdown (2.3.1)
|
16
|
+
rexml
|
17
|
+
method_source (1.0.0)
|
18
|
+
parallel (1.20.1)
|
19
|
+
parser (3.0.1.1)
|
20
|
+
ast (~> 2.4.1)
|
21
|
+
pastel (0.8.0)
|
22
|
+
tty-color (~> 0.5)
|
23
|
+
pry (0.13.1)
|
24
|
+
coderay (~> 1.1)
|
25
|
+
method_source (~> 1.0)
|
26
|
+
rainbow (3.0.0)
|
27
|
+
rake (13.0.3)
|
28
|
+
regexp_parser (2.1.1)
|
29
|
+
rexml (3.2.5)
|
30
|
+
rouge (3.26.0)
|
31
|
+
rspec (3.10.0)
|
32
|
+
rspec-core (~> 3.10.0)
|
33
|
+
rspec-expectations (~> 3.10.0)
|
34
|
+
rspec-mocks (~> 3.10.0)
|
35
|
+
rspec-core (3.10.1)
|
36
|
+
rspec-support (~> 3.10.0)
|
37
|
+
rspec-expectations (3.10.1)
|
38
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
39
|
+
rspec-support (~> 3.10.0)
|
40
|
+
rspec-mocks (3.10.2)
|
41
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
42
|
+
rspec-support (~> 3.10.0)
|
43
|
+
rspec-support (3.10.2)
|
44
|
+
rubocop (1.14.0)
|
45
|
+
parallel (~> 1.10)
|
46
|
+
parser (>= 3.0.0.0)
|
47
|
+
rainbow (>= 2.2.2, < 4.0)
|
48
|
+
regexp_parser (>= 1.8, < 3.0)
|
49
|
+
rexml
|
50
|
+
rubocop-ast (>= 1.5.0, < 2.0)
|
51
|
+
ruby-progressbar (~> 1.7)
|
52
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
53
|
+
rubocop-ast (1.5.0)
|
54
|
+
parser (>= 3.0.1.1)
|
55
|
+
ruby-progressbar (1.11.0)
|
56
|
+
strings (0.2.1)
|
57
|
+
strings-ansi (~> 0.2)
|
58
|
+
unicode-display_width (>= 1.5, < 3.0)
|
59
|
+
unicode_utils (~> 1.4)
|
60
|
+
strings-ansi (0.2.0)
|
61
|
+
tty-color (0.6.0)
|
62
|
+
tty-cursor (0.7.1)
|
63
|
+
tty-markdown (0.7.0)
|
64
|
+
kramdown (>= 1.16.2, < 3.0)
|
65
|
+
pastel (~> 0.8)
|
66
|
+
rouge (~> 3.14)
|
67
|
+
strings (~> 0.2.0)
|
68
|
+
tty-color (~> 0.5)
|
69
|
+
tty-screen (~> 0.8)
|
70
|
+
tty-prompt (0.23.1)
|
71
|
+
pastel (~> 0.8)
|
72
|
+
tty-reader (~> 0.8)
|
73
|
+
tty-reader (0.9.0)
|
74
|
+
tty-cursor (~> 0.7)
|
75
|
+
tty-screen (~> 0.8)
|
76
|
+
wisper (~> 2.0)
|
77
|
+
tty-screen (0.8.1)
|
78
|
+
unicode-display_width (2.0.0)
|
79
|
+
unicode_utils (1.4.0)
|
80
|
+
wisper (2.0.1)
|
81
|
+
|
82
|
+
PLATFORMS
|
83
|
+
x86_64-darwin-19
|
84
|
+
|
85
|
+
DEPENDENCIES
|
86
|
+
pry-shell!
|
87
|
+
rake (~> 13.0)
|
88
|
+
rspec (~> 3.0)
|
89
|
+
rubocop (~> 1.7)
|
90
|
+
|
91
|
+
BUNDLED WITH
|
92
|
+
2.2.16
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2021 Mehmet Emin INAC
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Pry::Shell
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/pry/shell`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'pry-shell'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle install
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install pry-shell
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/pry-shell.
|
36
|
+
|
37
|
+
## License
|
38
|
+
|
39
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "pry/shell"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
a = 1
|
15
|
+
|
16
|
+
binding.pry_shell
|
data/bin/setup
ADDED
data/exe/pry-shell
ADDED
data/lib/pry/shell.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "shell/version"
|
4
|
+
require_relative "shell/client"
|
5
|
+
require_relative "shell/command"
|
6
|
+
require_relative "shell/logger"
|
7
|
+
require_relative "shell/registry"
|
8
|
+
require_relative "shell/server"
|
9
|
+
require_relative "shell/session"
|
10
|
+
require_relative "shell/io/base"
|
11
|
+
require_relative "shell/io/input"
|
12
|
+
require_relative "shell/io/output"
|
13
|
+
require_relative "shell/patches/object"
|
14
|
+
require_relative "shell/patches/repl"
|
15
|
+
require_relative "shell/ui"
|
16
|
+
require_relative "shell/ui/base"
|
17
|
+
require_relative "shell/ui/about"
|
18
|
+
require_relative "shell/ui/list"
|
19
|
+
require_relative "shell/ui/menu"
|
20
|
+
require_relative "shell/ui/session"
|
21
|
+
|
22
|
+
class Pry
|
23
|
+
class Shell
|
24
|
+
DEFAULT_HOST = "localhost"
|
25
|
+
DEFAULT_PORT = "8787"
|
26
|
+
|
27
|
+
class << self
|
28
|
+
attr_reader :registry
|
29
|
+
|
30
|
+
def run(host:, port:, auto_connect:)
|
31
|
+
@registry = Registry.new(auto_connect)
|
32
|
+
|
33
|
+
new(host, port, registry).run
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(host, port, registry)
|
38
|
+
@host = host
|
39
|
+
@port = port
|
40
|
+
@registry = registry
|
41
|
+
end
|
42
|
+
|
43
|
+
def run
|
44
|
+
run_server
|
45
|
+
draw_ui
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
attr_reader :host, :port, :registry
|
51
|
+
|
52
|
+
def run_server
|
53
|
+
Server.new(host, port, registry).run
|
54
|
+
end
|
55
|
+
|
56
|
+
def draw_ui
|
57
|
+
UI.draw!
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "optparse"
|
4
|
+
require "pry/shell"
|
5
|
+
|
6
|
+
class Pry
|
7
|
+
class Shell
|
8
|
+
class CLI
|
9
|
+
class << self
|
10
|
+
def run
|
11
|
+
options.parse!
|
12
|
+
|
13
|
+
Shell.run(**config)
|
14
|
+
|
15
|
+
join_drb_thread
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def config
|
21
|
+
@config ||= {
|
22
|
+
host: DEFAULT_HOST,
|
23
|
+
port: DEFAULT_PORT,
|
24
|
+
auto_connect: false
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def options # rubocop:disable Metrics/MethodLength
|
29
|
+
@parser = OptionParser.new do |o|
|
30
|
+
o.banner = "Usage: bundle exec pry-shell [options]"
|
31
|
+
|
32
|
+
o.on "-h", "--host HOST", "Host name" do |arg|
|
33
|
+
config[:host] = arg
|
34
|
+
end
|
35
|
+
|
36
|
+
o.on "-p", "--post PORT", "Port of the shell application" do |arg|
|
37
|
+
config[:port] = arg
|
38
|
+
end
|
39
|
+
|
40
|
+
o.on "-a", "--auto-connect", "Connect automatically to the first Pry session" do
|
41
|
+
config[:auto_connect] = true
|
42
|
+
end
|
43
|
+
|
44
|
+
o.on "-v", "--version", "Print version and exit" do
|
45
|
+
puts "Pry-shell #{Pry::Shell::VERSION}"
|
46
|
+
exit 0
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def join_drb_thread
|
52
|
+
DRb.thread.join
|
53
|
+
rescue StandardError
|
54
|
+
Process.kill("TERM", Process.pid)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "drb"
|
4
|
+
|
5
|
+
class Pry
|
6
|
+
class Shell
|
7
|
+
class Client
|
8
|
+
# As we are sending the instances of this class to the clients,
|
9
|
+
# we should make sure the instance lives on the server.
|
10
|
+
include DRb::DRbUndumped
|
11
|
+
|
12
|
+
attr_reader :id
|
13
|
+
|
14
|
+
def initialize(id, process_name, host, location)
|
15
|
+
@id = id
|
16
|
+
@process_name = process_name
|
17
|
+
@host = host
|
18
|
+
@location = location
|
19
|
+
@created_at = Time.now
|
20
|
+
end
|
21
|
+
|
22
|
+
def input
|
23
|
+
@input ||= IO::Input.new(self, Pry.config.input)
|
24
|
+
end
|
25
|
+
|
26
|
+
def output
|
27
|
+
@output ||= IO::Output.new(self, Pry.config.output)
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
"#{process_name} @#{host} - #{full_location}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def current?
|
35
|
+
Shell.registry.current == self
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
attr_reader :process_name, :host, :location, :created_at
|
41
|
+
|
42
|
+
def full_location
|
43
|
+
location.join(":")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Pry
|
4
|
+
class Shell
|
5
|
+
class Command
|
6
|
+
EXIT_COMMANDS = %w[exit !!!].freeze
|
7
|
+
DISC_COMMAND = "\\m"
|
8
|
+
DISC_FALLBACK = "whereami"
|
9
|
+
|
10
|
+
def self.execute(client, string)
|
11
|
+
case string
|
12
|
+
when *EXIT_COMMANDS
|
13
|
+
Shell.registry.remove(client) && string
|
14
|
+
when DISC_COMMAND
|
15
|
+
Shell.registry.disconnect(client) && DISC_FALLBACK
|
16
|
+
else
|
17
|
+
string
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Pry
|
4
|
+
class Shell
|
5
|
+
module IO
|
6
|
+
class Base
|
7
|
+
include DRb::DRbUndumped
|
8
|
+
|
9
|
+
def initialize(client, object)
|
10
|
+
@client = client
|
11
|
+
@object = object
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
attr_reader :client, :object
|
17
|
+
|
18
|
+
def wait_until_current
|
19
|
+
sleep(0.5) until current?
|
20
|
+
end
|
21
|
+
|
22
|
+
def current?
|
23
|
+
client.current?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "readline"
|
4
|
+
|
5
|
+
class Pry
|
6
|
+
class Shell
|
7
|
+
module IO
|
8
|
+
class Input < Base
|
9
|
+
def readline(prompt)
|
10
|
+
wait_until_current
|
11
|
+
|
12
|
+
string = object.readline(prompt, true)
|
13
|
+
|
14
|
+
Command.execute(client, string)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Pry
|
4
|
+
class Shell
|
5
|
+
module IO
|
6
|
+
class Output < Base
|
7
|
+
def puts(data)
|
8
|
+
wait_until_current
|
9
|
+
|
10
|
+
object.puts data
|
11
|
+
end
|
12
|
+
|
13
|
+
def print(data)
|
14
|
+
wait_until_current
|
15
|
+
|
16
|
+
object.print data
|
17
|
+
end
|
18
|
+
|
19
|
+
def printf(data)
|
20
|
+
wait_until_current
|
21
|
+
|
22
|
+
object.printf data
|
23
|
+
end
|
24
|
+
|
25
|
+
def write(data)
|
26
|
+
wait_until_current
|
27
|
+
|
28
|
+
object.printf data
|
29
|
+
end
|
30
|
+
|
31
|
+
def <<(data)
|
32
|
+
wait_until_current
|
33
|
+
|
34
|
+
object << data
|
35
|
+
self
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "logger"
|
4
|
+
require "forwardable"
|
5
|
+
require "fileutils"
|
6
|
+
|
7
|
+
class Pry
|
8
|
+
class Shell
|
9
|
+
class Logger
|
10
|
+
LOG_FOLDER = "tmp"
|
11
|
+
|
12
|
+
class << self
|
13
|
+
extend Forwardable
|
14
|
+
|
15
|
+
def_delegators :logger, :unknown, :fatal, :error, :warn, :info, :debug
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def logger
|
20
|
+
@logger ||= ::Logger.new(log_file)
|
21
|
+
end
|
22
|
+
|
23
|
+
def log_file
|
24
|
+
File.open(log_file_name, "w+").tap { |f| f.sync = true }
|
25
|
+
end
|
26
|
+
|
27
|
+
def log_file_name
|
28
|
+
FileUtils.mkdir_p LOG_FOLDER
|
29
|
+
|
30
|
+
File.join(LOG_FOLDER, "pry_shell.log")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Pry
|
4
|
+
class Shell
|
5
|
+
module Patches
|
6
|
+
module Object
|
7
|
+
def pry_shell(host: DEFAULT_HOST, port: DEFAULT_PORT)
|
8
|
+
Session.run(self, host: host, port: port)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Object.prepend(Pry::Shell::Patches::Object)
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pry"
|
4
|
+
|
5
|
+
class Pry
|
6
|
+
class Shell
|
7
|
+
module Patches
|
8
|
+
module Repl
|
9
|
+
def read_line(current_prompt)
|
10
|
+
handle_read_errors do
|
11
|
+
setup_auto_completion
|
12
|
+
read_command(current_prompt)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def setup_auto_completion
|
19
|
+
if coolline_available?
|
20
|
+
input.completion_proc = proc do |cool|
|
21
|
+
completions = @pry.complete cool.completed_word
|
22
|
+
completions.compact
|
23
|
+
end
|
24
|
+
elsif input.respond_to? :completion_proc=
|
25
|
+
input.completion_proc = proc do |inp|
|
26
|
+
@pry.complete inp
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def read_command(current_prompt)
|
32
|
+
if readline_available?
|
33
|
+
set_readline_output
|
34
|
+
input_readline(current_prompt, false) # false since we'll add it manually
|
35
|
+
elsif coolline_available?
|
36
|
+
input_readline(current_prompt)
|
37
|
+
else
|
38
|
+
input_readline(current_prompt)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
Pry::REPL.prepend(Pry::Shell::Patches::Repl)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "drb"
|
4
|
+
|
5
|
+
class Pry
|
6
|
+
class Shell
|
7
|
+
class Registry
|
8
|
+
include DRb::DRbUndumped
|
9
|
+
|
10
|
+
attr_reader :auto_connect, :clients, :current
|
11
|
+
|
12
|
+
def initialize(auto_connect)
|
13
|
+
@auto_connect = auto_connect
|
14
|
+
@clients = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def register(id:, name:, host:, location:)
|
18
|
+
Client.new(id, name, host, location).tap do |client|
|
19
|
+
Logger.debug("New client connected - #{client}")
|
20
|
+
|
21
|
+
@clients[id] = client
|
22
|
+
connect_to(client) if auto_connect
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def connect_to(client)
|
27
|
+
# This thread is necessary because `UI::Session.draw!`
|
28
|
+
# puts the main thread into sleep!
|
29
|
+
Thread.start do
|
30
|
+
UI::Session.draw!
|
31
|
+
|
32
|
+
@current = client
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def disconnect(_client)
|
37
|
+
@current = nil
|
38
|
+
|
39
|
+
UI.restart!
|
40
|
+
end
|
41
|
+
|
42
|
+
def remove(client)
|
43
|
+
@current = nil
|
44
|
+
|
45
|
+
@clients.delete(client.id)
|
46
|
+
|
47
|
+
UI.restart!
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "drb"
|
4
|
+
|
5
|
+
class Pry
|
6
|
+
class Shell
|
7
|
+
class Server
|
8
|
+
def initialize(host, port, registry)
|
9
|
+
@host = host
|
10
|
+
@port = port
|
11
|
+
@registry = registry
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
Logger.info("Running Drb server on '#{uri}'")
|
16
|
+
|
17
|
+
DRb.start_service(uri, registry)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :host, :port, :registry
|
23
|
+
|
24
|
+
def uri
|
25
|
+
"druby://#{host}:#{port}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "socket"
|
4
|
+
require "securerandom"
|
5
|
+
|
6
|
+
class Pry
|
7
|
+
class Shell
|
8
|
+
class Session
|
9
|
+
class << self
|
10
|
+
def run(object, host:, port:)
|
11
|
+
new(object, host, port).run
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(object, host, port)
|
16
|
+
@object = object
|
17
|
+
@host = host
|
18
|
+
@port = port
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
setup
|
23
|
+
|
24
|
+
Pry.start(object)
|
25
|
+
rescue DRb::DRbConnError
|
26
|
+
puts "DRb connection failed!"
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :object, :host, :port
|
32
|
+
|
33
|
+
def client
|
34
|
+
@client ||= registry.register(id: id, **attributes)
|
35
|
+
end
|
36
|
+
|
37
|
+
def registry
|
38
|
+
@registry ||= begin
|
39
|
+
DRb.start_service
|
40
|
+
DRbObject.new(nil, uri)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def id
|
45
|
+
@id ||= SecureRandom.uuid
|
46
|
+
end
|
47
|
+
|
48
|
+
def attributes
|
49
|
+
{ name: $PROGRAM_NAME, host: Socket.gethostname, location: object.source_location }
|
50
|
+
end
|
51
|
+
|
52
|
+
def uri
|
53
|
+
"druby://#{host}:#{port}"
|
54
|
+
end
|
55
|
+
|
56
|
+
def setup
|
57
|
+
Pry.config.input = client.input
|
58
|
+
Pry.config.output = client.output
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
data/lib/pry/shell/ui.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Pry
|
4
|
+
class Shell
|
5
|
+
class UI
|
6
|
+
StopMainUI = Class.new(StandardError)
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def draw!
|
10
|
+
UI::Menu.draw!
|
11
|
+
rescue StopMainUI
|
12
|
+
sleep
|
13
|
+
draw!
|
14
|
+
end
|
15
|
+
|
16
|
+
def stop!
|
17
|
+
Thread.main.raise StopMainUI.new
|
18
|
+
end
|
19
|
+
|
20
|
+
def restart!
|
21
|
+
Thread.main.wakeup
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Pry
|
4
|
+
class Shell
|
5
|
+
class UI
|
6
|
+
class About < Base
|
7
|
+
HEADER = "PRY-SHELL About"
|
8
|
+
CONTENT = <<~MARKDOWN
|
9
|
+
pry-shell version `0.0.1`
|
10
|
+
|
11
|
+
Pry-shell provides you a standalone shell for accessing multiple `pry` sessions running on different processes.
|
12
|
+
You can switch between sessions by using XXX command.
|
13
|
+
|
14
|
+
Written by Mehmet Emin INAC.
|
15
|
+
MARKDOWN
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "tty-markdown"
|
4
|
+
require "tty-prompt"
|
5
|
+
|
6
|
+
class Pry
|
7
|
+
class Shell
|
8
|
+
class UI
|
9
|
+
class Base
|
10
|
+
SEPERATOR = "---"
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def draw!
|
14
|
+
clear!
|
15
|
+
draw_header
|
16
|
+
draw_seperator
|
17
|
+
draw_content
|
18
|
+
draw_seperator
|
19
|
+
draw_footer
|
20
|
+
end
|
21
|
+
|
22
|
+
def stop_main_ui!
|
23
|
+
UI.stop!
|
24
|
+
end
|
25
|
+
|
26
|
+
def clear!
|
27
|
+
system("clear") || system("cls")
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def draw_header
|
33
|
+
print_markdown(header)
|
34
|
+
end
|
35
|
+
|
36
|
+
def draw_seperator
|
37
|
+
print_markdown(SEPERATOR)
|
38
|
+
end
|
39
|
+
|
40
|
+
def draw_content
|
41
|
+
print_markdown(content)
|
42
|
+
end
|
43
|
+
|
44
|
+
def draw_footer
|
45
|
+
return_menu_prompt
|
46
|
+
end
|
47
|
+
|
48
|
+
def header
|
49
|
+
"##{const_get(:HEADER)}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def content
|
53
|
+
const_get(:CONTENT)
|
54
|
+
end
|
55
|
+
|
56
|
+
def prompt
|
57
|
+
@prompt ||= TTY::Prompt.new
|
58
|
+
end
|
59
|
+
|
60
|
+
def print_markdown(text)
|
61
|
+
puts TTY::Markdown.parse(text)
|
62
|
+
end
|
63
|
+
|
64
|
+
def return_menu_prompt
|
65
|
+
prompt.keypress("Press any key to return to the menu...")
|
66
|
+
|
67
|
+
Menu.draw!
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Pry
|
4
|
+
class Shell
|
5
|
+
class UI
|
6
|
+
class List < Base
|
7
|
+
HEADER = "PRY-SHELL Sessions"
|
8
|
+
EMPTY_LIST = "No session available!"
|
9
|
+
TO_MENU_ITEM = { name: "Go back to menu", value: "menu" }.freeze
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def draw_content
|
13
|
+
clients.empty? ? draw_empty_list : draw_list
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def draw_empty_list
|
19
|
+
print_markdown(EMPTY_LIST)
|
20
|
+
end
|
21
|
+
|
22
|
+
def draw_list
|
23
|
+
id = prompt.select("Select session to connect", select_values)
|
24
|
+
|
25
|
+
id == "menu" ? to_menu : connect_to(id)
|
26
|
+
end
|
27
|
+
|
28
|
+
def select_values
|
29
|
+
clients.map { |id, client| { name: client.to_s, value: id } }
|
30
|
+
.push(TO_MENU_ITEM)
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_menu
|
34
|
+
Menu.draw!
|
35
|
+
end
|
36
|
+
|
37
|
+
def connect_to(id)
|
38
|
+
Shell.registry.connect_to(clients[id])
|
39
|
+
end
|
40
|
+
|
41
|
+
def clients
|
42
|
+
Shell.registry.clients
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Pry
|
4
|
+
class Shell
|
5
|
+
class UI
|
6
|
+
class Menu < Base
|
7
|
+
HEADER = "PRY-SHELL Main Menu"
|
8
|
+
ITEMS = [
|
9
|
+
{ name: "1) Available sessions", value: "list" },
|
10
|
+
{ name: "2) About pry-shell", value: "about" },
|
11
|
+
{ name: "3) Quit", value: "quit" }
|
12
|
+
].freeze
|
13
|
+
MENU_ACTIONS = {
|
14
|
+
"list" => -> { List.draw! },
|
15
|
+
"about" => -> { About.draw! },
|
16
|
+
"quit" => -> { clear! && exit(0) }
|
17
|
+
}.freeze
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def draw_content
|
21
|
+
selection = prompt.select("Select a menu item", ITEMS)
|
22
|
+
|
23
|
+
switch_to(selection)
|
24
|
+
end
|
25
|
+
|
26
|
+
def switch_to(selected_ui)
|
27
|
+
MENU_ACTIONS[selected_ui].call
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Pry
|
4
|
+
class Shell
|
5
|
+
class UI
|
6
|
+
class Session < Base
|
7
|
+
HEADER = "PRY-SHELL"
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def draw!
|
11
|
+
stop_main_ui!
|
12
|
+
clear!
|
13
|
+
draw_header
|
14
|
+
draw_seperator
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/pry-shell.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/pry/shell/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "pry-shell"
|
7
|
+
spec.version = Pry::Shell::VERSION
|
8
|
+
spec.authors = ["Mehmet Emin INAC"]
|
9
|
+
spec.email = ["mehmetemininac@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "Provides remote pry sessions."
|
12
|
+
spec.description = "pry-shell gem provides multiple remote pry sessions."
|
13
|
+
spec.homepage = "https://github.com/meinac/pry-shell"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = "https://github.com/meinac/pry-shell"
|
19
|
+
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
21
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
23
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
|
24
|
+
end
|
25
|
+
spec.bindir = "exe"
|
26
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ["lib"]
|
28
|
+
|
29
|
+
spec.add_dependency "pry", "~> 0.13.0"
|
30
|
+
spec.add_dependency "tty-markdown"
|
31
|
+
spec.add_dependency "tty-prompt"
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pry-shell
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mehmet Emin INAC
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-05-10 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.13.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.13.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: tty-markdown
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: tty-prompt
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: pry-shell gem provides multiple remote pry sessions.
|
56
|
+
email:
|
57
|
+
- mehmetemininac@gmail.com
|
58
|
+
executables:
|
59
|
+
- pry-shell
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- ".rspec"
|
65
|
+
- ".rubocop.yml"
|
66
|
+
- Gemfile
|
67
|
+
- Gemfile.lock
|
68
|
+
- LICENSE.txt
|
69
|
+
- README.md
|
70
|
+
- Rakefile
|
71
|
+
- bin/console
|
72
|
+
- bin/setup
|
73
|
+
- exe/pry-shell
|
74
|
+
- lib/pry/shell.rb
|
75
|
+
- lib/pry/shell/cli.rb
|
76
|
+
- lib/pry/shell/client.rb
|
77
|
+
- lib/pry/shell/command.rb
|
78
|
+
- lib/pry/shell/io/base.rb
|
79
|
+
- lib/pry/shell/io/input.rb
|
80
|
+
- lib/pry/shell/io/output.rb
|
81
|
+
- lib/pry/shell/logger.rb
|
82
|
+
- lib/pry/shell/patches/object.rb
|
83
|
+
- lib/pry/shell/patches/repl.rb
|
84
|
+
- lib/pry/shell/registry.rb
|
85
|
+
- lib/pry/shell/server.rb
|
86
|
+
- lib/pry/shell/session.rb
|
87
|
+
- lib/pry/shell/ui.rb
|
88
|
+
- lib/pry/shell/ui/about.rb
|
89
|
+
- lib/pry/shell/ui/base.rb
|
90
|
+
- lib/pry/shell/ui/list.rb
|
91
|
+
- lib/pry/shell/ui/menu.rb
|
92
|
+
- lib/pry/shell/ui/session.rb
|
93
|
+
- lib/pry/shell/version.rb
|
94
|
+
- pry-shell.gemspec
|
95
|
+
homepage: https://github.com/meinac/pry-shell
|
96
|
+
licenses:
|
97
|
+
- MIT
|
98
|
+
metadata:
|
99
|
+
homepage_uri: https://github.com/meinac/pry-shell
|
100
|
+
source_code_uri: https://github.com/meinac/pry-shell
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
require_paths:
|
104
|
+
- lib
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 2.5.0
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubygems_version: 3.0.8
|
117
|
+
signing_key:
|
118
|
+
specification_version: 4
|
119
|
+
summary: Provides remote pry sessions.
|
120
|
+
test_files: []
|