flippy consoleで上下反転文字の不思議な感覚を味わってみませんか?
少し前に文字列を上下反転して出力するflippy
というgemを書きましたよ。
このgemにはflippyコマンドが付いていて、ターミナルで簡単に反転文字が作れるようになっているのでした。
% flippy Hello, world!
¡plɹoʍ ‘olləH
で、今回これをもう少し拡張して、専用コンソールで反転文字を打てるflippy console
というのを追加しましたので、お知らせしますね。flippy consoleはflippyコマンドに--console
オプションを付加することで起動することができます。
デモをスクリーンキャストしたので見てください。
カーソルが追随しないところがイマイチですけど、どうですか?ちょっと面白いですよね?実際に入力してると、ちょっと不思議な感覚があります。
実用性ですか?
ん〜、タッチタイピング練習具とか、右脳発育訓練具とかどうでしょう…
少し逆立ちして考えてみます… それよりもここでは実装方法を少し書き残しておきますね。
termios
flippy consoleの実現にはプログラムからターミナルの設定を変更する必要があります。つまりターミナルはデフォルトで打った文字をエコーバックします。また、リターンキーを押すまで入力を受け付けないモードにセットされています(これを「カノニカルモード」といいます)。flippy consoleではこのエコーを無効にすると共に、入力文字をすぐに読み取るモード(非カノニカルモード)に一時的に変える必要があります。
これらの設定を変更するにはターミナルの標準インタフェースとなっているtermios
構造体というものにアクセスしてその設定を変える必要があります。幸いRubyにはruby-termios
というtermiosのラッパーがあるのでこれを使えば、Rubyからターミナルの設定を変更できます。
次のような感じで使います。
require "termios"
$stdin.extend Termios
begin
term_preset = $stdin.tcgetattr
term = term_preset.dup
[Termios::ICANON, Termios::ECHO].each { |flag| term.lflag &= ~flag }
$stdin.tcsetattr(Termios::TCSANOW, term)
# ターミナルを使う
ensure
$stdin.tcsetattr(Termios::TCSANOW, term_preset)
end
$stdin.extend Termios
で標準入力オブジェクトへTermiosモジュールのメソッドをmix-inします。#tcgetattr
で現在のターミナルの設定を読み出し、これを保存しておきます。termiosには4種類の設定モード、入力(iflag)、出力(oflag)、制御(cflag)、ローカル(lflag)があって、その何れかに所望の設定を行います。
設定は対象モードに対しフラグをビット単位で論理和することで実現します(ex. term.iflag ||= flag)。対象ビットをクリアするには先のコードのようにterm.flag &= ~flag
とします。ここでは、カノニカルモード(ICANON)とエコー(ECHO)の設定をオフにしています。
この状態で#tcsetattr
を使い、ターミナルに変更を加えたtermiosをセットします。第一引数のTCSANOW
は直ちに設定を反映させるための指定です。以上でターミナルはエコー無し、非カノニカルモードとして動作するようになります。ターミナルの使用後は設定を元に戻しておきます。
エスケープシーケンス
flippy consoleではカーソルの移動を制御する必要があります。カーソルの制御には標準添付ライブラリのcurses
がありますが、簡単な制御ならエスケープシーケンスで行うことができます。flippyでは今ひとつ上手くできてないですが。
print "\e[5;10H" # カーソルをスクリーンの5行10列に移動
print "\e[1A" # カーソルを一つ上に移動
print "\e[1B" # カーソルを一つ下に移動
print "\e[1C" # カーソルを一つ前に移動
print "\e[1D" # カーソルを一つ後ろに移動
色の制御もエスケープシーケンスで行います。これについては以前に記事を書いているので、そちらを参考にして下さい。本当は文字単位で色の制御を行えるようにしたかったのですが、実装が難しくて諦めました。
エスケープシーケンスの詳細については以下が参考になります。
以上、flippy consoleの紹介と実装の簡単な説明でした。あなたもflippy -c
して不思議な感覚味わってみませんか?
あっ、いい使い道思いついた…ムカつく上司の端末に(ry
該当箇所のコードも一応貼っておきます。
関連記事:cursesを使ったサンプル
blog comments powered by Disqus