Skip to content

Instantly share code, notes, and snippets.

@arika
Last active February 9, 2018 07:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arika/3111a07b0073adc3308ba80f8f1fdcc0 to your computer and use it in GitHub Desktop.
Save arika/3111a07b0073adc3308ba80f8f1fdcc0 to your computer and use it in GitHub Desktop.
workaround to avoid suspending rb-readline by 'Ctrl-Y'. https://arika.org/2017/11/10/rb-readline-and-ctrl-y/
# macOSでのrb-readline使用時の"\C-y"サスペンド問題の回避
if defined?(::RbReadline) && $".grep(/\/rbreadline.rb\z/)
stty = `stty -a`
stty_ccs = { 'dsusp' => '^Y', 'lnext' => '^V' }
stty_ccs.delete_if {|cc, key| /\b#{Regexp.quote("#{cc} = #{key}")};/ !~ stty }
unless stty_ccs.empty?
system('stty', *stty_ccs.keys.inject([]) {|opts, cc| opts << cc << 'undef' })
IRB.conf[:AT_EXIT] << proc do
system('stty', *stty_ccs.to_a.flatten)
end
end
end
# macOSでのrb-readline使用時の"\C-y"サスペンド問題の回避
stty_ccs = {}
nest_level = -1
Pry.hooks.add_hook(:when_started, 'avoid dsusp') do
if defined?(::RbReadline) && $".grep(/\/rbreadline.rb\z/)
stty = `stty -a`
stty_ccs = { 'dsusp' => '^Y', 'lnext' => '^V' }
stty_ccs.delete_if {|cc, key| /\b#{Regexp.quote("#{cc} = #{key}")};/ !~ stty }
end
end
Pry.hooks.add_hook(:before_session, 'count nest level') do
nest_level += 1
end
Pry.hooks.add_hook(:before_session, 'avoid dsusp') do |_, _, pry|
system('stty', *stty_ccs.keys.inject([]) {|opts, cc| opts << cc << 'undef' }) if nest_level.zero? && !stty_ccs.empty?
end
Pry.hooks.add_hook(:after_session, 'avoid dsusp') do |_, _, pry|
system('stty', *stty_ccs.to_a.flatten) if nest_level.zero? && !stty_ccs.empty?
end
Pry.hooks.add_hook(:after_session, 'count nest level') do
nest_level -= 1
end
require 'pty'
require 'timeout'
irb_start = [
'gem "rb-readline"', # rb-readlineを使用しない場合はコメントアウト
'require "irb"',
'IRB.start',
].join('; ')
timeout = 5
bash_prompt = /bash-[.\d]+\$ \z/
irb_prompt = />> \z/
ios = [
bash_prompt,
"echo cat test\n",
bash_prompt,
"cat\n",
"aaa\n",
"bbb\n",
"\C-d",
bash_prompt,
"echo readline test\n",
bash_prompt,
"ruby -e '#{irb_start}' -- -f --prompt-mode=simple\n",
irb_prompt,
":ccc\n",
irb_prompt,
":ddd", "\C-a", "\C-k", "eee = ", "\C-y", "\n",
irb_prompt,
":fff\n",
irb_prompt,
"quit\n",
bash_prompt,
"echo done.\n",
bash_prompt,
"exit\n",
]
result = 'OK'
wait = nil
buf = ''
PTY.spawn('bash --norc') do |r, w, _p|
w.sync = true
begin
Timeout.timeout(timeout) do
ios.each do |obj|
if obj.is_a?(String)
w.write obj
$stderr.write '+'
next
end
wait = obj
loop do
buf << r.readpartial(1024)
break if wait.match(buf)
$stderr.write '-'
sleep 0.1
end
$stderr.write '.'
end
end
buf << r.readpartial(1024)
rescue Timeout::Error
result = "ERROR: couldn't get #{wait.inspect}"
ensure
w.close
r.close
end
end
$stderr.write "\n#{'-' * 78}\n"
print "RESULT = #{result}\n\n#{buf}"
$ ruby test.rb
-.+-.++++-.+-.+--.+-.++++++---
------------------------------------------------------------------------------
RESULT = ERROR: couldn't get />> \z/
bash-3.2$ echo cat test
cat test
bash-3.2$ cat
aaa
bbb
aaa
bbb
bash-3.2$ echo readline test
readline test
ode=simpleruby -e 'gem "rb-readline"; require "irb"; IRB.start' -- -f --prompt-m
>> :ccc
=> :ccc
>> eee =
[1]+ Stopped ruby -e 'gem "rb-readline"; require "irb"; IRB.start' -- -f --prompt-mode=simple
bash-3.2$
$ ruby test.rb
.+-.++++-.+-.+--.+--.++++++---.+--.+-.+-.+
------------------------------------------------------------------------------
RESULT = OK
bash-3.2$ echo cat test
cat test
bash-3.2$ cat
aaa
bbb
aaa
bbb
bash-3.2$ echo readline test
readline test
bash-3.2$ ruby -e 'require "irb"; IRB.start' -- -f --prompt-mode=simple
>> :ccc
=> :ccc
>> eee = :ddd
=> :ddd
>> :fff
=> :fff
>> quit
bash-3.2$ echo done.
done.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment