Skip to content

Instantly share code, notes, and snippets.

@ttdoda ttdoda/fall.rb
Last active Nov 15, 2018

Embed
What would you like to do?
端末が落ちます (下方向に)
#!/usr/bin/env ruby
#
# fall.rb -- 端末が落ちます (下方向に)
#
# 対応端末:
# dttermのウィンドウ制御シーケンスに一通り対応していれば動くはず……だけど意外と少ないんだ、これが
# 手元で動作するのを確認したのは xterm, Tera Term, mintty の三つ
#
# License: CC0
#$gravity = 2.4
$gravity = 3
require 'timeout'
include Math
$stdout.sync = 1
def getCSIstr(t = 1)
resp = ""
Timeout.timeout(t) {
while c = $stdin.getc
case c.ord
when 0x1b
c = $stdin.getc
break if c.chr == "["
$stdin.ungetc c
when 0x9c
break
when 3, 4
return ""
when 0..0x1f
raise
end
end
while c = $stdin.getc
case c.ord
when 0x20..0x3f
resp << c.chr
when 0x40..0x7e
resp << c.chr
break
else
raise
end
end
}
resp
end
def moveTo(x, y)
print "\e[3;#{x.to_i};#{y.to_i}t"
end
def resizeTerm(h, w)
print "\e[8;#{h};#{w}t"
end
def getCurrentPosition
begin
system("stty raw -echo")
print "\e[13t"
case getCSIstr(0)
when ""
return [-1, -1]
when /(\d+)\;(\d+);(\d+)t/
raise unless $1 == "3"
else
raise
end
[$2.to_i, $3.to_i]
ensure
system("stty #{$saved_mode}")
end
end
def do_fall(x, y, maxY)
dirV = 0
begin
while true
y += dirV
if y > maxY
y = maxY
dirV /= 2
break if dirV <= 1
dirV = -dirV
elsif y < 0
y = 0
end
dirV += $gravity
moveTo x, y
sleep 0.02
end
end
end
maxX = 0
maxY = 0
termWidth = -1
termHeight = -1
origX = -1
origY = -1
$saved_mode = `stty -g`
begin
system("stty raw -echo")
print "\e[18t"
raise unless /(\d+)\;(\d+);(\d+)t/ =~ getCSIstr && $1 == "8"
termHeight = $2.to_i
termWidth = $3.to_i
print "\e[13t"
raise unless /(\d+)\;(\d+);(\d+)t/ =~ getCSIstr && $1 == "3"
origX = $2.to_i
origY = $3.to_i
resizeTerm 25, 81
print "\e[14t"
raise unless /(\d+)\;(\d+);(\d+)t/ =~ getCSIstr && $1 == "4"
tmpHeight = $2.to_i
tmpWidth = $3.to_i
resizeTerm 24, 80
print "\e[14t"
raise unless /(\d+)\;(\d+);(\d+)t/ =~ getCSIstr && $1 == "4"
winHeight = $2.to_i
winWidth = $3.to_i
cellHeight = tmpHeight - winHeight
cellWidth = tmpWidth - winWidth
print "\e[19t"
raise unless /(\d+)\;(\d+);(\d+)t/ =~ getCSIstr && $1 == "9"
rootHeight = $2.to_i * cellHeight
rootWidth = $3.to_i * cellWidth
maxY = rootHeight - winHeight
maxX = rootWidth - winWidth
rescue Timeout::Error, RuntimeError
puts "not supported terminal"
resizeTerm(termHeight, termWidth) if termHeight > 0 && termWidth > 0
moveTo(origX, origY) if origX >= 0 && origY >= 0
exit 1
ensure
system("stty #{$saved_mode}")
end
begin
do_fall(origX, origY, maxY)
while true
sleep 1
x, y = getCurrentPosition
break if x < 0
do_fall(x, y, maxY) if y != maxY
end
rescue Interrupt
exit 0
ensure
resizeTerm(termHeight, termWidth)
moveTo(origX, origY)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.