/usr/lib/ruby/vendor_ruby/pry/repl.rb is in pry 0.10.3-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | require 'forwardable'
class Pry
class REPL
extend Forwardable
def_delegators :@pry, :input, :output
# @return [Pry] The instance of {Pry} that the user is controlling.
attr_accessor :pry
# Instantiate a new {Pry} instance with the given options, then start a
# {REPL} instance wrapping it.
# @option options See {Pry#initialize}
def self.start(options)
new(Pry.new(options)).start
end
# Create an instance of {REPL} wrapping the given {Pry}.
# @param [Pry] pry The instance of {Pry} that this {REPL} will control.
# @param [Hash] options Options for this {REPL} instance.
# @option options [Object] :target The initial target of the session.
def initialize(pry, options = {})
@pry = pry
@indent = Pry::Indent.new
if options[:target]
@pry.push_binding options[:target]
end
end
# Start the read-eval-print loop.
# @return [Object?] If the session throws `:breakout`, return the value
# thrown with it.
# @raise [Exception] If the session throws `:raise_up`, raise the exception
# thrown with it.
def start
prologue
Pry::InputLock.for(:all).with_ownership { repl }
ensure
epilogue
end
private
# Set up the repl session.
# @return [void]
def prologue
pry.exec_hook :before_session, pry.output, pry.current_binding, pry
# Clear the line before starting Pry. This fixes issue #566.
if pry.config.correct_indent
Kernel.print Pry::Helpers::BaseHelpers.windows_ansi? ? "\e[0F" : "\e[0G"
end
end
# The actual read-eval-print loop.
#
# The {REPL} instance is responsible for reading and looping, whereas the
# {Pry} instance is responsible for evaluating user input and printing
# return values and command output.
#
# @return [Object?] If the session throws `:breakout`, return the value
# thrown with it.
# @raise [Exception] If the session throws `:raise_up`, raise the exception
# thrown with it.
def repl
loop do
case val = read
when :control_c
output.puts ""
pry.reset_eval_string
when :no_more_input
output.puts "" if output.tty?
break
else
output.puts "" if val.nil? && output.tty?
return pry.exit_value unless pry.eval(val)
end
end
end
# Clean up after the repl session.
# @return [void]
def epilogue
pry.exec_hook :after_session, pry.output, pry.current_binding, pry
end
# Read a line of input from the user.
# @return [String] The line entered by the user.
# @return [nil] On `<Ctrl-D>`.
# @return [:control_c] On `<Ctrl+C>`.
# @return [:no_more_input] On EOF.
def read
@indent.reset if pry.eval_string.empty?
current_prompt = pry.select_prompt
indentation = pry.config.auto_indent ? @indent.current_prefix : ''
val = read_line("#{current_prompt}#{indentation}")
# Return nil for EOF, :no_more_input for error, or :control_c for <Ctrl-C>
return val unless String === val
if pry.config.auto_indent
original_val = "#{indentation}#{val}"
indented_val = @indent.indent(val)
if output.tty? && pry.config.correct_indent && Pry::Helpers::BaseHelpers.use_ansi_codes?
output.print @indent.correct_indentation(
current_prompt, indented_val,
original_val.length - indented_val.length
)
output.flush
end
else
indented_val = val
end
indented_val
end
# Manage switching of input objects on encountering `EOFError`s.
# @return [Object] Whatever the given block returns.
# @return [:no_more_input] Indicates that no more input can be read.
def handle_read_errors
should_retry = true
exception_count = 0
begin
yield
rescue EOFError
pry.config.input = Pry.config.input
if !should_retry
output.puts "Error: Pry ran out of things to read from! " \
"Attempting to break out of REPL."
return :no_more_input
end
should_retry = false
retry
# Handle <Ctrl+C> like Bash: empty the current input buffer, but don't
# quit. This is only for MRI 1.9; other versions of Ruby don't let you
# send Interrupt from within Readline.
rescue Interrupt
return :control_c
# If we get a random error when trying to read a line we don't want to
# automatically retry, as the user will see a lot of error messages
# scroll past and be unable to do anything about it.
rescue RescuableException => e
puts "Error: #{e.message}"
output.puts e.backtrace
exception_count += 1
if exception_count < 5
retry
end
puts "FATAL: Pry failed to get user input using `#{input}`."
puts "To fix this you may be able to pass input and output file " \
"descriptors to pry directly. e.g."
puts " Pry.config.input = STDIN"
puts " Pry.config.output = STDOUT"
puts " binding.pry"
return :no_more_input
end
end
# Returns the next line of input to be sent to the {Pry} instance.
# @param [String] current_prompt The prompt to use for input.
# @return [String?] The next line of input, or `nil` on <Ctrl-D>.
def read_line(current_prompt)
handle_read_errors do
if defined? Coolline and input.is_a? Coolline
input.completion_proc = proc do |cool|
completions = @pry.complete cool.completed_word
completions.compact
end
elsif input.respond_to? :completion_proc=
input.completion_proc = proc do |input|
@pry.complete input
end
end
if defined?(Readline) and input == Readline
input_readline(current_prompt, false) # false since we'll add it manually
elsif defined? Coolline and input.is_a? Coolline
input_readline(current_prompt)
else
if input.method(:readline).arity == 1
input_readline(current_prompt)
else
input_readline
end
end
end
end
def input_readline(*args)
Pry::InputLock.for(:all).interruptible_region do
input.readline(*args)
end
end
end
end
|