Last active
November 15, 2018 11:33
-
-
Save ttdoda/09f685bff1333c4393cde7b25887fca4 to your computer and use it in GitHub Desktop.
端末が落ちます (下方向に)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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