2021-02-15 10:30:30 -05:00
|
|
|
#!/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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-15 11:46:53 -05:00
|
|
|
opt.on('--dynamic-prompt-returns-empty') {
|
|
|
|
Reline.prompt_proc = proc { |l| [] }
|
|
|
|
}
|
2021-02-15 10:30:30 -05:00
|
|
|
opt.on('--auto-indent') {
|
|
|
|
AutoIndent.new
|
|
|
|
}
|
2021-09-09 15:58:35 -04:00
|
|
|
opt.on('--dialog VAL') { |v|
|
2021-09-09 15:36:55 -04:00
|
|
|
Reline.add_dialog_proc(:simple_dialog, lambda {
|
2021-09-09 19:15:00 -04:00
|
|
|
return nil if v.include?('nil')
|
2021-09-09 15:58:35 -04:00
|
|
|
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
|
2021-10-10 05:58:46 -04:00
|
|
|
elsif v.include?('fullwidth')
|
|
|
|
contents = <<~RUBY.split("\n")
|
|
|
|
Rubyとは...
|
|
|
|
|
|
|
|
オープンソースの動的なプログラミン
|
|
|
|
グ言語で、シンプルさと高い生産性を
|
|
|
|
備えています。エレガントな文法を持
|
|
|
|
ち、自然に読み書きができます。
|
|
|
|
RUBY
|
2021-09-09 15:58:35 -04:00
|
|
|
end
|
|
|
|
if v.include?('scrollkey')
|
|
|
|
dialog.trap_key = nil
|
|
|
|
if key and key.match?(dialog.name)
|
2021-09-09 22:23:42 -04:00
|
|
|
if dialog.pointer.nil?
|
|
|
|
dialog.pointer = 0
|
|
|
|
elsif dialog.pointer >= (contents.size - 1)
|
|
|
|
dialog.pointer = 0
|
2021-09-09 15:58:35 -04:00
|
|
|
else
|
2021-09-09 22:23:42 -04:00
|
|
|
dialog.pointer += 1
|
2021-09-09 15:58:35 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
dialog.trap_key = [?j.ord]
|
|
|
|
height = 4
|
|
|
|
end
|
2021-09-09 19:54:24 -04:00
|
|
|
scrollbar = false
|
|
|
|
if v.include?('scrollbar')
|
|
|
|
scrollbar = true
|
|
|
|
end
|
2021-10-09 10:07:18 -04:00
|
|
|
if v.include?('alt-scrollbar')
|
|
|
|
scrollbar = true
|
|
|
|
end
|
2021-09-09 22:23:42 -04:00
|
|
|
Reline::DialogRenderInfo.new(pos: cursor_pos, contents: contents, height: height, scrollbar: scrollbar)
|
|
|
|
})
|
2021-10-09 10:07:18 -04:00
|
|
|
if v.include?('alt-scrollbar')
|
|
|
|
ENV['RELINE_ALT_SCROLLBAR'] = '1'
|
|
|
|
end
|
2021-09-09 15:36:55 -04:00
|
|
|
}
|
2021-09-01 15:31:01 -04:00
|
|
|
opt.on('--complete') {
|
|
|
|
Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil|
|
2021-09-09 18:34:33 -04:00
|
|
|
%w{String ScriptError SyntaxError Signal}.select{ |c| c.start_with?(target) }
|
2021-09-01 15:31:01 -04:00
|
|
|
}
|
|
|
|
}
|
2021-09-08 18:22:53 -04:00
|
|
|
opt.on('--autocomplete') {
|
|
|
|
Reline.autocompletion = true
|
|
|
|
Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil|
|
2021-09-09 18:34:33 -04:00
|
|
|
%w{String Struct Symbol ScriptError SyntaxError Signal}.select{ |c| c.start_with?(target) }
|
2021-09-08 18:22:53 -04:00
|
|
|
}
|
|
|
|
}
|
2021-09-09 15:37:19 -04:00
|
|
|
opt.on('--autocomplete-long') {
|
|
|
|
Reline.autocompletion = true
|
|
|
|
Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil|
|
2021-09-30 07:55:50 -04:00
|
|
|
%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) }
|
2021-09-09 15:37:19 -04:00
|
|
|
}
|
|
|
|
}
|
2021-10-03 05:25:26 -04:00
|
|
|
opt.on('--autocomplete-super-long') {
|
|
|
|
Reline.autocompletion = true
|
|
|
|
Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil|
|
|
|
|
c = 'A'
|
|
|
|
2000.times.map{ s = "Str_#{c}"; c.succ!; s }.select{ |c| c.start_with?(target) }
|
|
|
|
}
|
|
|
|
}
|
2021-02-15 10:30:30 -05:00
|
|
|
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
|