pry-shell 0.2.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f78367d80e34ffed27c18d3dfea89c22f3efc65fde39b043ac07628d6715b9c
4
- data.tar.gz: 5b0e36dfdefe005810de67b5b41dcf4472b8e71744b325a2bdeab9be7bb42c6f
3
+ metadata.gz: 4b7c98d15684726ac960299f6b91bce6e5baae12c6c72d97c211150647026fce
4
+ data.tar.gz: 6b39ad64506fdc162e6f19220067aaad25a44e431d8f93533a4ae6a0f1f90b3a
5
5
  SHA512:
6
- metadata.gz: d7d03a089b432e1e91c0a4210965d8faca9ef584d06d633fda07c8abace3e671962d38bff45b6d328fc3728075591a08c280659a5094714a66acaf42c5e4bd8e
7
- data.tar.gz: 392014b4371beace17450468b5d2000ea1fb48419a5af4dc39c6d9ad346ff91ddf4ff38d20b3a259608463dabe4220d61cf181eaa566f78a2d7cbe3f6fe4c93a
6
+ metadata.gz: d534b80562457c6005d49be9551b59dcc26127d1cdace9426fe17d76aeb45cd4bf1ff784d6cd8d1de3ca90390c699f0835c7f17573f216310840ee6aa5df5313
7
+ data.tar.gz: 0a82202c3e05b20767d063cb6537b687bf5eafc96a29928e6a51a92a95068a319c3251e5b58d0808639231caa86fbc4c8eb36f13daf8775176816e3ea119c967
data/.gitignore CHANGED
@@ -6,6 +6,7 @@
6
6
  /pkg/
7
7
  /spec/reports/
8
8
  /tmp/
9
+ /log/
9
10
 
10
11
  # rspec failure tracking
11
12
  .rspec_status
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in pry-shell.gemspec
6
6
  gemspec
7
7
 
8
+ gem "pry-byebug"
8
9
  gem "rake", "~> 13.0"
9
10
  gem "rspec", "~> 3.0"
10
11
  gem "rubocop", "~> 1.7"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pry-shell (0.2.0)
4
+ pry-shell (0.5.0)
5
5
  pry (~> 0.13.0)
6
6
  tty-markdown
7
7
  tty-prompt
@@ -10,6 +10,7 @@ GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
12
  ast (2.4.2)
13
+ byebug (11.1.3)
13
14
  coderay (1.1.3)
14
15
  diff-lcs (1.4.4)
15
16
  kramdown (2.3.1)
@@ -23,6 +24,9 @@ GEM
23
24
  pry (0.13.1)
24
25
  coderay (~> 1.1)
25
26
  method_source (~> 1.0)
27
+ pry-byebug (3.9.0)
28
+ byebug (~> 11.0)
29
+ pry (~> 0.13.0)
26
30
  rainbow (3.0.0)
27
31
  rake (13.0.3)
28
32
  regexp_parser (2.1.1)
@@ -83,6 +87,7 @@ PLATFORMS
83
87
  x86_64-darwin-19
84
88
 
85
89
  DEPENDENCIES
90
+ pry-byebug
86
91
  pry-shell!
87
92
  rake (~> 13.0)
88
93
  rspec (~> 3.0)
data/README.md CHANGED
@@ -22,7 +22,7 @@ Or install it yourself as:
22
22
 
23
23
  ## Usage
24
24
 
25
- TODO: Write usage instructions here
25
+ Here's a [video showing how to use pry-shell](https://www.youtube.com/watch?v=Lzs_PL_BySo).
26
26
 
27
27
  ## Development
28
28
 
data/bin/console CHANGED
@@ -11,6 +11,20 @@ require "pry/shell"
11
11
  # require "pry"
12
12
  # Pry.start
13
13
 
14
- a = 1
14
+ def foo1
15
+ binding.pry_shell
15
16
 
16
- binding.pry_shell
17
+ foo2
18
+ end
19
+
20
+ def foo2
21
+ foo3
22
+ end
23
+
24
+ def foo3
25
+ 5
26
+ end
27
+
28
+ a = 5 + foo1
29
+
30
+ puts a
data/lib/pry-shell.rb ADDED
@@ -0,0 +1 @@
1
+ require 'pry/shell'
data/lib/pry/shell.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require_relative "shell/version"
4
4
  require_relative "shell/client"
5
5
  require_relative "shell/command"
6
+ require_relative "shell/configuration"
6
7
  require_relative "shell/logger"
7
8
  require_relative "shell/registry"
8
9
  require_relative "shell/server"
@@ -15,6 +16,8 @@ require_relative "shell/io/pager"
15
16
  require_relative "shell/ui"
16
17
  require_relative "shell/ui/base"
17
18
  require_relative "shell/ui/about"
19
+ require_relative "shell/ui/configuration"
20
+ require_relative "shell/ui/configuration/auto_connect"
18
21
  require_relative "shell/ui/list"
19
22
  require_relative "shell/ui/menu"
20
23
  require_relative "shell/ui/session"
@@ -25,12 +28,11 @@ class Pry
25
28
  DEFAULT_PORT = "1881"
26
29
 
27
30
  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
31
+ def run
32
+ run_server
33
+ draw_ui
34
+ rescue TTY::Reader::InputInterrupt, Interrupt
35
+ exit
34
36
  end
35
37
 
36
38
  def active_shell_options(thread: Thread.current)
@@ -40,29 +42,32 @@ class Pry
40
42
  def active_shell_options=(value)
41
43
  Thread.current[:active_shell_options] = value
42
44
  end
43
- end
44
45
 
45
- def initialize(host, port, registry)
46
- @host = host
47
- @port = port
48
- @registry = registry
49
- end
46
+ def clear_shell_options!
47
+ self.active_shell_options = nil
48
+ end
50
49
 
51
- def run
52
- run_server
53
- draw_ui
54
- end
50
+ def remove_active_connection!
51
+ active_shell_options&.fetch(:remove_connection)&.call
52
+ end
55
53
 
56
- private
54
+ def configuration
55
+ @configuration ||= Configuration.new
56
+ end
57
57
 
58
- attr_reader :host, :port, :registry
58
+ def registry
59
+ @registry ||= Registry.new
60
+ end
59
61
 
60
- def run_server
61
- Server.new(host, port, registry).run
62
- end
62
+ private
63
63
 
64
- def draw_ui
65
- UI.draw!
64
+ def run_server
65
+ Server.run
66
+ end
67
+
68
+ def draw_ui
69
+ UI.draw!
70
+ end
66
71
  end
67
72
  end
68
73
  end
data/lib/pry/shell/cli.rb CHANGED
@@ -10,35 +10,27 @@ class Pry
10
10
  def run
11
11
  options.parse!
12
12
 
13
- Shell.run(**config)
13
+ Shell.run
14
14
 
15
15
  join_drb_thread
16
16
  end
17
17
 
18
18
  private
19
19
 
20
- def config
21
- @config ||= {
22
- host: DEFAULT_HOST,
23
- port: DEFAULT_PORT,
24
- auto_connect: false
25
- }
26
- end
27
-
28
20
  def options # rubocop:disable Metrics/MethodLength
29
21
  @parser = OptionParser.new do |o|
30
22
  o.banner = "Usage: bundle exec pry-shell [options]"
31
23
 
32
24
  o.on "-h", "--host HOST", "Host name" do |arg|
33
- config[:host] = arg
25
+ Shell.configuration.host = arg
34
26
  end
35
27
 
36
28
  o.on "-p", "--post PORT", "Port of the shell application" do |arg|
37
- config[:port] = arg
29
+ Shell.configuration.port = arg
38
30
  end
39
31
 
40
- o.on "-a", "--auto-connect", "Connect automatically to the first Pry session" do
41
- config[:auto_connect] = true
32
+ o.on "--disable-auto-connect", "Disable auto connect feature" do
33
+ Shell.configuration.auto_connect = false
42
34
  end
43
35
 
44
36
  o.on "-v", "--version", "Print version and exit" do
@@ -9,13 +9,16 @@ class Pry
9
9
  # we should make sure the instance lives on the server.
10
10
  include DRb::DRbUndumped
11
11
 
12
+ MAX_PROCESS_NAME = 50
13
+
12
14
  attr_reader :id
13
15
 
14
- def initialize(id, process_name, host, location)
16
+ def initialize(id, process_name, host, pid, location)
15
17
  @id = id
16
18
  @process_name = process_name
17
19
  @host = host
18
20
  @location = location
21
+ @pid = pid
19
22
  @created_at = Time.now
20
23
  end
21
24
 
@@ -36,7 +39,7 @@ class Pry
36
39
  end
37
40
 
38
41
  def to_s
39
- "#{process_name} @#{host} - #{full_location}"
42
+ "[#{pid}] \"#{humanized_process_name}\" @\"#{host}\" - #{full_location}"
40
43
  end
41
44
 
42
45
  def current?
@@ -45,11 +48,15 @@ class Pry
45
48
 
46
49
  private
47
50
 
48
- attr_reader :process_name, :host, :location, :created_at
51
+ attr_reader :process_name, :host, :pid, :location, :created_at
49
52
 
50
53
  def full_location
51
54
  location.join(":")
52
55
  end
56
+
57
+ def humanized_process_name
58
+ process_name.length > MAX_PROCESS_NAME ? "#{process_name[0..50]}..." : process_name
59
+ end
53
60
  end
54
61
  end
55
62
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ class Shell
5
+ class Configuration
6
+ CONFIG_KEYS = {
7
+ host: "localhost",
8
+ port: "1881",
9
+ auto_connect: true
10
+ }.freeze
11
+
12
+ CONFIG_KEYS.each do |config_key, default_value|
13
+ attr_writer config_key
14
+
15
+ define_method(config_key) do
16
+ return default_value unless instance_variable_defined?("@#{config_key}")
17
+
18
+ instance_variable_get("@#{config_key}")
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -7,7 +7,7 @@ require "fileutils"
7
7
  class Pry
8
8
  class Shell
9
9
  class Logger
10
- LOG_FOLDER = "tmp"
10
+ LOG_FOLDER = "log"
11
11
 
12
12
  class << self
13
13
  extend Forwardable
@@ -4,8 +4,8 @@ class Pry
4
4
  class Shell
5
5
  module Patches
6
6
  module Object
7
- def pry_shell(host: DEFAULT_HOST, port: DEFAULT_PORT)
8
- Session.run(self, host: host, port: port)
7
+ def pry_shell(host: DEFAULT_HOST, port: DEFAULT_PORT, with_byebug: true)
8
+ Session.run(self, host: host, port: port, with_byebug: with_byebug)
9
9
  end
10
10
  end
11
11
  end
@@ -1,24 +1,87 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class Pry
4
- class Shell
5
- module Patches
6
- module PryByebug
7
- def start_with_pry_byebug(target = nil, options = {})
8
- return start_without_pry_byebug(target, options) if Shell.active_shell_options
9
-
10
- super
3
+ begin
4
+ require "pry-byebug"
5
+ require "pry-byebug/pry_ext"
6
+
7
+ module Byebug
8
+ class PryShellProcessor < PryProcessor
9
+ class << self
10
+ def start
11
+ Byebug.start
12
+ Setting[:autolist] = false
13
+ Context.processor = self
14
+ Byebug.current_context.step_out(7, true)
15
+ at_exit { teardown! }
16
+ end
17
+
18
+ private
19
+
20
+ def teardown!
21
+ Pry::Shell.remove_active_connection!
22
+ Pry::Shell.clear_shell_options!
23
+ end
24
+ end
25
+
26
+ def resume_pry
27
+ run do
28
+ pry_started? ? start_new_pry_repl : start_new_pry_session
11
29
  end
30
+ rescue DRb::DRbConnError
31
+ puts "DRb connection failed!"
32
+ end
33
+
34
+ private
35
+
36
+ def pry_started?
37
+ defined?(@pry) && @pry
38
+ end
39
+
40
+ def start_new_pry_session
41
+ @pry = Pry.start_without_pry_byebug(frame._binding, Pry::Shell.active_shell_options)
42
+ end
43
+
44
+ def start_new_pry_repl
45
+ Pry::Shell::Repl.new(@pry, target: frame._binding).start
12
46
  end
13
47
  end
14
48
  end
15
- end
16
49
 
17
- begin
18
- require "pry-byebug"
19
- require "pry-byebug/pry_ext"
50
+ class Pry
51
+ class Shell
52
+ module Patches
53
+ module PryByebug
54
+ def start_with_pry_byebug(target = nil, options = {})
55
+ return start_with_pry_shell(target) if Shell.active_shell_options
56
+
57
+ super
58
+ end
59
+
60
+ def start_with_pry_shell(target)
61
+ if Shell.active_shell_options[:enable_byebug?]
62
+ ::Byebug::PryShellProcessor.start
63
+ else
64
+ start_without_pry_byebug(target, Shell.active_shell_options)
65
+ end
66
+ end
67
+ end
68
+
69
+ module PryProcessor
70
+ def start
71
+ super
72
+
73
+ # We should step out one more frame as we are
74
+ # prepending another module to the hierarchy
75
+ ::Byebug.current_context.step_out(5, true)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
20
81
 
21
82
  Pry.singleton_class.prepend(Pry::Shell::Patches::PryByebug)
22
83
  Pry.singleton_class.alias_method(:start, :start_with_pry_byebug)
84
+
85
+ Byebug::PryProcessor.singleton_class.prepend(Pry::Shell::Patches::PryProcessor)
23
86
  rescue LoadError # rubocop:disable Lint/SuppressedException
24
87
  end
@@ -7,20 +7,19 @@ class Pry
7
7
  class Registry
8
8
  include DRb::DRbUndumped
9
9
 
10
- attr_reader :auto_connect, :clients, :current, :mutex
10
+ attr_reader :clients, :current, :mutex
11
11
 
12
- def initialize(auto_connect)
13
- @auto_connect = auto_connect
12
+ def initialize
14
13
  @clients = {}
15
14
  @mutex = Mutex.new
16
15
  end
17
16
 
18
- def register(id:, name:, host:, location:)
19
- Client.new(id, name, host, location).tap do |client|
17
+ def register(id:, name:, host:, pid:, location:)
18
+ Client.new(id, name, host, pid, location).tap do |client|
20
19
  Logger.debug("New client connected - #{client}")
21
20
 
22
21
  @clients[id] = client
23
- connect_to(client) if auto_connect
22
+ connect_to(client) if Shell.configuration.auto_connect
24
23
  end
25
24
  end
26
25
 
@@ -5,24 +5,18 @@ require "drb"
5
5
  class Pry
6
6
  class Shell
7
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
8
+ class << self
9
+ def run
10
+ Logger.info("Running Drb server on '#{uri}'")
19
11
 
20
- private
12
+ DRb.start_service(uri, Shell.registry)
13
+ end
21
14
 
22
- attr_reader :host, :port, :registry
15
+ private
23
16
 
24
- def uri
25
- "druby://#{host}:#{port}"
17
+ def uri
18
+ "druby://#{Shell.configuration.host}:#{Shell.configuration.port}"
19
+ end
26
20
  end
27
21
  end
28
22
  end
@@ -13,15 +13,16 @@ class Pry
13
13
  class Shell
14
14
  class Session
15
15
  class << self
16
- def run(object, host:, port:)
17
- new(object, host, port).run
16
+ def run(object, host:, port:, with_byebug:)
17
+ new(object, host, port, with_byebug).run
18
18
  end
19
19
  end
20
20
 
21
- def initialize(object, host, port)
21
+ def initialize(object, host, port, with_byebug)
22
22
  @object = object
23
23
  @host = host
24
24
  @port = port
25
+ @with_byebug = with_byebug
25
26
  end
26
27
 
27
28
  def run
@@ -31,15 +32,22 @@ class Pry
31
32
  rescue DRb::DRbConnError
32
33
  puts "DRb connection failed!"
33
34
  ensure
34
- Shell.active_shell_options = nil
35
+ # Since we run `Byebug.current_context.step_out` this ensure
36
+ # block already runs and clears the options which are necessary
37
+ # to setup the Byebug.
38
+ # We are clearing this options in `PryShellProcessor` to ensure
39
+ # they do not leak.
40
+ Shell.clear_shell_options! unless enable_byebug?
35
41
  end
36
42
 
37
43
  private
38
44
 
39
- attr_reader :object, :host, :port
45
+ attr_reader :object, :host, :port, :with_byebug
40
46
 
41
47
  def pry_options
42
48
  {
49
+ remove_connection: -> { registry.remove(client) },
50
+ enable_byebug?: enable_byebug?,
43
51
  driver: Pry::Shell::Repl,
44
52
  pager: false,
45
53
  input: client.input,
@@ -49,6 +57,12 @@ class Pry
49
57
  }
50
58
  end
51
59
 
60
+ # Setting the `with_byebug` option as `true` is not enough as the
61
+ # `pry-byebug` gem can be missing which we are currently depending on.
62
+ def enable_byebug?
63
+ with_byebug && defined?(::Byebug::PryShellProcessor)
64
+ end
65
+
52
66
  def client
53
67
  @client ||= registry.register(id: id, **attributes)
54
68
  end
@@ -65,7 +79,12 @@ class Pry
65
79
  end
66
80
 
67
81
  def attributes
68
- { name: $PROGRAM_NAME, host: Socket.gethostname, location: object.source_location }
82
+ {
83
+ name: $PROGRAM_NAME,
84
+ host: Socket.gethostname,
85
+ pid: Process.pid,
86
+ location: object.source_location
87
+ }
69
88
  end
70
89
 
71
90
  def uri
data/lib/pry/shell/ui.rb CHANGED
@@ -8,6 +8,7 @@ class Pry
8
8
  class << self
9
9
  def draw!
10
10
  UI::Menu.draw!
11
+ draw!
11
12
  rescue StopMainUI
12
13
  sleep
13
14
  draw!
@@ -9,7 +9,7 @@ class Pry
9
9
  pry-shell version "#{VERSION}"
10
10
 
11
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 the "\\h" command.
12
+ You can switch between sessions by going back to the menu using the "\\m" command.
13
13
 
14
14
  Written by Mehmet Emin INAC.
15
15
  MARKDOWN
@@ -42,7 +42,7 @@ class Pry
42
42
  end
43
43
 
44
44
  def draw_footer
45
- return_menu_prompt
45
+ prompt.keypress("Press any key to return to the menu...")
46
46
  end
47
47
 
48
48
  def header
@@ -60,12 +60,6 @@ class Pry
60
60
  def print_markdown(text)
61
61
  puts TTY::Markdown.parse(text)
62
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
63
  end
70
64
  end
71
65
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ class Shell
5
+ class UI
6
+ class Configuration < Base
7
+ HEADER = "PRY-SHELL Configuration"
8
+ ITEMS = [
9
+ { name: "Auto-connect", value: "auto_connect" },
10
+ { name: "Go back to menu", value: "menu" }
11
+ ].freeze
12
+ ACTIONS = {
13
+ "auto_connect" => -> { AutoConnect.draw! & draw! },
14
+ "menu" => -> {}
15
+ }.freeze
16
+
17
+ class << self
18
+ def draw_content
19
+ selection = prompt.select("Select a configuration item to change it's value", ITEMS)
20
+
21
+ ACTIONS[selection].call
22
+ end
23
+
24
+ def draw_footer; end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Pry
4
+ class Shell
5
+ class UI
6
+ class Configuration
7
+ class AutoConnect < Base
8
+ class << self
9
+ def draw!
10
+ Shell.configuration.auto_connect = show_prompt
11
+ end
12
+
13
+ private
14
+
15
+ def show_prompt
16
+ prompt.select("Accept connections automatically?", cycle: true) do |config|
17
+ config.default default_value
18
+
19
+ config.choice "yes", true
20
+ config.choice "no", false
21
+ end
22
+ end
23
+
24
+ def default_value
25
+ Shell.configuration.auto_connect ? "yes" : "no"
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -7,11 +7,13 @@ class Pry
7
7
  HEADER = "PRY-SHELL Main Menu"
8
8
  ITEMS = [
9
9
  { name: "1) Available sessions", value: "list" },
10
- { name: "2) About pry-shell", value: "about" },
11
- { name: "3) Quit", value: "quit" }
10
+ { name: "2) Configuration", value: "configuration" },
11
+ { name: "3) About pry-shell", value: "about" },
12
+ { name: "4) Quit", value: "quit" }
12
13
  ].freeze
13
14
  MENU_ACTIONS = {
14
15
  "list" => -> { List.draw! },
16
+ "configuration" => -> { Configuration.draw! },
15
17
  "about" => -> { About.draw! },
16
18
  "quit" => -> { clear! && exit(0) }
17
19
  }.freeze
@@ -23,6 +25,9 @@ class Pry
23
25
  switch_to(selection)
24
26
  end
25
27
 
28
+ # Override this to remove "press any key" prompt
29
+ def draw_footer; end
30
+
26
31
  def switch_to(selected_ui)
27
32
  MENU_ACTIONS[selected_ui].call
28
33
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  class Pry
4
4
  class Shell
5
- VERSION = "0.2.0"
5
+ VERSION = "0.5.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pry-shell
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mehmet Emin INAC
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-05-12 00:00:00.000000000 Z
11
+ date: 2021-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -71,10 +71,12 @@ files:
71
71
  - bin/console
72
72
  - bin/setup
73
73
  - exe/pry-shell
74
+ - lib/pry-shell.rb
74
75
  - lib/pry/shell.rb
75
76
  - lib/pry/shell/cli.rb
76
77
  - lib/pry/shell/client.rb
77
78
  - lib/pry/shell/command.rb
79
+ - lib/pry/shell/configuration.rb
78
80
  - lib/pry/shell/io/base.rb
79
81
  - lib/pry/shell/io/editor.rb
80
82
  - lib/pry/shell/io/input.rb
@@ -92,6 +94,8 @@ files:
92
94
  - lib/pry/shell/ui.rb
93
95
  - lib/pry/shell/ui/about.rb
94
96
  - lib/pry/shell/ui/base.rb
97
+ - lib/pry/shell/ui/configuration.rb
98
+ - lib/pry/shell/ui/configuration/auto_connect.rb
95
99
  - lib/pry/shell/ui/list.rb
96
100
  - lib/pry/shell/ui/menu.rb
97
101
  - lib/pry/shell/ui/session.rb