mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
138 lines
3.7 KiB
Ruby
Executable file
138 lines
3.7 KiB
Ruby
Executable file
#!/usr/bin/env ruby
|
|
|
|
require 'reline'
|
|
require 'optparse'
|
|
require_relative 'termination_checker'
|
|
|
|
opt = OptionParser.new
|
|
opt.on('--prompt-list-cache-timeout VAL') { |v|
|
|
Reline::LineEditor.__send__(:remove_const, :PROMPT_LIST_CACHE_TIMEOUT)
|
|
Reline::LineEditor::PROMPT_LIST_CACHE_TIMEOUT = v.to_f
|
|
}
|
|
opt.on('--dynamic-prompt') {
|
|
Reline.prompt_proc = proc { |lines|
|
|
lines.each_with_index.map { |l, i|
|
|
'[%04d]> ' % i
|
|
}
|
|
}
|
|
}
|
|
opt.on('--broken-dynamic-prompt') {
|
|
Reline.prompt_proc = proc { |lines|
|
|
range = lines.size > 1 ? (0..(lines.size - 2)) : (0..0)
|
|
lines[range].each_with_index.map { |l, i|
|
|
'[%04d]> ' % i
|
|
}
|
|
}
|
|
}
|
|
opt.on('--dynamic-prompt-returns-empty') {
|
|
Reline.prompt_proc = proc { |l| [] }
|
|
}
|
|
opt.on('--auto-indent') {
|
|
AutoIndent.new
|
|
}
|
|
opt.on('--dialog VAL') { |v|
|
|
Reline.add_dialog_proc(:simple_dialog, lambda {
|
|
return nil if v.include?('nil')
|
|
if v.include?('simple')
|
|
contents = <<~RUBY.split("\n")
|
|
Ruby is...
|
|
A dynamic, open source programming
|
|
language with a focus on simplicity
|
|
and productivity. It has an elegant
|
|
syntax that is natural to read and
|
|
easy to write.
|
|
RUBY
|
|
elsif v.include?('long')
|
|
contents = <<~RUBY.split("\n")
|
|
Ruby is...
|
|
A dynamic, open
|
|
source programming
|
|
language with a
|
|
focus on simplicity
|
|
and productivity.
|
|
It has an elegant
|
|
syntax that is
|
|
natural to read
|
|
and easy to write.
|
|
RUBY
|
|
end
|
|
if v.include?('scrollkey')
|
|
dialog.trap_key = nil
|
|
if key and key.match?(dialog.name)
|
|
if context.pointer.nil?
|
|
context.pointer = 0
|
|
elsif context.pointer >= (contents.size - 1)
|
|
context.pointer = 0
|
|
else
|
|
context.pointer += 1
|
|
end
|
|
end
|
|
dialog.trap_key = [?j.ord]
|
|
height = 4
|
|
end
|
|
scrollbar = false
|
|
if v.include?('scrollbar')
|
|
scrollbar = true
|
|
end
|
|
Reline::DialogRenderInfo.new(pos: cursor_pos, contents: contents, height: height, pointer: context.pointer, scrollbar: scrollbar)
|
|
}, Struct.new(:pointer).new)
|
|
}
|
|
opt.on('--complete') {
|
|
Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil|
|
|
%w{String ScriptError SyntaxError Signal}.select{ |c| c.start_with?(target) }
|
|
}
|
|
}
|
|
opt.on('--autocomplete') {
|
|
Reline.autocompletion = true
|
|
Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil|
|
|
%w{String Struct Symbol ScriptError SyntaxError Signal}.select{ |c| c.start_with?(target) }
|
|
}
|
|
}
|
|
opt.on('--autocomplete-long') {
|
|
Reline.autocompletion = true
|
|
Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil|
|
|
%w{String Struct Symbol StopIteration SystemCallError SystemExit SystemStackError ScriptError SyntaxError Signal SizedQueue Set SecureRandom Socket StringIO StringScanner Shellwords Syslog Singleton SDBM}.select{ |c| c.start_with?(target) }
|
|
}
|
|
}
|
|
opt.parse!(ARGV)
|
|
|
|
begin
|
|
stty_save = `stty -g`.chomp
|
|
rescue
|
|
end
|
|
|
|
begin
|
|
prompt = ENV['RELINE_TEST_PROMPT'] || 'prompt> '
|
|
puts 'Multiline REPL.'
|
|
checker = TerminationChecker.new
|
|
while code = Reline.readmultiline(prompt, true) { |code| checker.terminated?(code) }
|
|
case code.chomp
|
|
when 'exit', 'quit', 'q'
|
|
exit 0
|
|
when ''
|
|
# NOOP
|
|
else
|
|
begin
|
|
result = eval(code)
|
|
puts "=> #{result.inspect}"
|
|
rescue ScriptError, StandardError => e
|
|
puts "Traceback (most recent call last):"
|
|
e.backtrace.reverse_each do |f|
|
|
puts " #{f}"
|
|
end
|
|
puts e.message
|
|
end
|
|
end
|
|
end
|
|
rescue Interrupt
|
|
puts '^C'
|
|
`stty #{stty_save}` if stty_save
|
|
exit 0
|
|
ensure
|
|
`stty #{stty_save}` if stty_save
|
|
end
|
|
begin
|
|
puts
|
|
rescue Errno::EIO
|
|
# Maybe the I/O has been closed.
|
|
end
|