Pythonのblessingsを使ってみよう
Blessingsは、cursesで制限となるいくつかの前提をなくし、美しいTUIコード書くことができます。
curses ライブラリが利用できるプラットフォームで実行することができます。
スタイル、色、ちょっとした位置合わせを、必ずしも最初に画面全体をクリアすることなく、行うことができます。
行儀の良いコマンドラインアプリのように、プログラムが終了した後、バッファに1画面分以上のスクロールバックを残します。
tigetstr や tparm などの煩わしい C言語ライクな呼び出しを行う必要がありません。
まずは、次の2つのコードをみてみましょう。
code: python
# c01_curses.py
from curses import tigetstr, setupterm, tparm
from fcntl import ioctl
from os import isatty
import struct
import sys
from termios import TIOCGWINSZ
# If we want to tolerate having our output piped to other commands or
# files without crashing, we need to do all this branching:
if hasattr(sys.stdout, 'fileno') and isatty(sys.stdout.fileno()):
setupterm()
sc = tigetstr('sc')
cup = tigetstr('cup')
rc = tigetstr('rc')
underline = tigetstr('smul')
normal = tigetstr('sgr0')
else:
sc = cup = rc = underline = normal = ''
print(sc) # Save cursor position.
if cup:
# tigetnum('lines') doesn't always update promptly, hence this:
height = struct.unpack('hhhh', ioctl(0, TIOCGWINSZ, '\000' * 8))0 print tparm(cup, height - 1, 0) # Move cursor to bottom.
print(f'This is {underline}underlined{normal}!')
print(rc) # Restore cursor position.
code: python
# c02_using_blessings.py
from blessings import Terminal
term = Terminal()
with term.location(0, term.height - 1):
print('This is', term.underline('pretty!'))
随分とスッキリして読みやすくなりますよね。
オプションにより、スクリプトの出力をファイルにリダイレクトしたときは、ユーザが見たくない端末制御コードを抑制することができます。
Blessings が提供するもの
Blessingsが提供するものは Terminalクラス 1つだけです。Terminalクラスのインスタンスオブジェクトを作成すると、端末を使用しているかどうかを判断し、端末を使用している場合は必要な初期化設定を行います。その後は、Terminalクラスのメソッドを呼び出したり、属性を参照して端末制御を行うことができます。
code: python
from blessings import Terminal
term = Terminal()
簡単な書式設定
多くの便利な書式コードがターミナルの属性として利用できます。
たとえば、次のようなものです。
code: python
# c03_formatting.py
from blessings import Terminal
term = Terminal()
msg = 'I am ' + term.bold + 'bold' + term.normal + '!'
print(msg)
これらは元々は文字列ですが、呼び出し可能なラッパーとして使用することもできます。その場合は、その後にnormalを付加する必要はありません。
code: python
# c04_formatting_as_wrapper.py
from blessings import Terminal
term = Terminal()
print( f"I am {term.bold('bold')} !")
ある程度の簡潔さを保ちつつ、きめ細かい制御をしたいのであれば、Pythonの文字列フォーマットと組み合わせることで、属性へのアクセスを容易にすることができます。
code: python
# c05_string_format.py
from blessings import Terminal
term = Terminal()
msg = ( f'All your {term.red}base {term.underline}'
f'are belong to us{term.normal}' )
print(msg)
# この場合は、str().format() メソッドの方が簡潔になる
msg = ( 'All your {t.red}base {t.underline}'
'are belong to us{t.normal}' ).format(t=term)
print(msg)
サポートされているスタイル
bold
reverse
underline
no_underline (underlineの無効化する)
blink
normali (全ての色やスタイルを無効化する)
端末によっては制御できないスタイル
dim
italic , no_italic
shadow , no_shadow
standout , no_standout
subscript , no_subscript
superscript , no_superscript
flash
色の制御
前景色、背景色ともに16色を制御することができます。
code: python
# c06_colors.py
from blessings import Terminal
term = Terminal()
msg = term.red + term.on_green + 'Red on green? Ick!' + term.normal
print(msg)
msg = ( term.bright_red
+ term.on_bright_blue
+ 'This is even worse!'
+ term.normal )
print(msg)
code: python
# c07_colors_as_wrapper.py
from blessings import Terminal
term = Terminal()
msg = term.red_on_green('Red on green? Ick!')
print(msg)
msg = term.yellow('I can barely see it.')
print(msg)
.on_blue() のように on_ を前につけると、前景色ではなく背景色を設定することができます。各色には明るいバージョンもあります。例: .on_bright_blue()
色には数値のインターフェースもあり、0から15までの整数を受け取ることができます。
サポートされている色
ほぼ全ての端末で利用できるのは次の8色です。
black
red
green
yellow
blue
magenta
cyan
white
組み合わせた書式設定
数の書式設定を一度に行うことができます。
code: python
from blessings import Terminal
term = Terminal()
print(term.bold_underline_green_on_yellow + 'Woo' + term.normal)
あるいは、新しく作った属性をラッパーのように使って、
暗黙のうちにすべてを元に戻すこともできます。
code: python
print(term.bold_underline_green_on_yellow('Woo')))
この複合記法は、ユーザーが書式をカスタマイズできるようにしたい場合に便利です。
コマンドラインで bold_green のような書式指定子を渡してもらい、
書式設定を行う際に getattr(term, that_option)('Your text') を実行すればいいだ>けです。
カーソルの移動
カーソルを動かして特定の場所にテキストを出力したい場合、いくつかの選択肢があります。
一時的に移動する
画面の下にあるプログレスバーを更新するときなどでは、一時的に移動させることになります。Terminal には、これ>を簡潔に行うためのコンテキストマネージャが用意されています。
code: python
from blessings import Terminal
from blessings import Terminal: term = Terminal()
with term.location(0, term.height - 1):
print('Here is bottom.')
print('This is back where I came from.')
location() のパラメータはx、yの順ですが、どちらか一方だけを渡して、もう一方は >そのままにすることも可能です。
code: python
with term.location(y=10):
print('We changed just the row.')
一連の移動呼び出し(下記参照)を行っていて、終了後にカーソルを元の位置に戻したい場合は、引数なしで location() を呼べば、カーソル位置の復元だけを行います。
code: python
with term.location():
print(term.move(1, 1) + 'Python')
print(term.move(9, 9) + 'Osaka')
location() は端末に内蔵された位置記憶機構を使用するため、複数の呼び出しをネストすることはできないことに注意してください。一番外側で location() を呼び出して、内側で move() のような単純なものを使うようにしてください。
恒久的な移動
単に移動したいだけで、戻ることを心配しないのであれば、次のようにします。
code: python
from blessings import Terminal
term = Terminal()
print(term.move(10, 1) + 'Python Osaka!')
move() ー カーソルを他の場所に移動します。パラメータは y 座標、x 座標の順に指定します。
move_x() ー カーソルを与えられた列に移動させる。
move_y() ー カーソルを与えられた行に移動させる。
これらは単に、多くの端末制御機能をラップして、わかりやすい名前をつけただけです。tparm() を常に呼び出すのではなく、単純にこれらの関数を呼び出し可能な文字列となります。単に表示するだけなら生の制御文字列ですが、関数のようにパラメータを渡せば、完全にパラメータ化されます。
1文字ずつチ移動
カーソルを様々な方向に1文字ずつ移動させる移動メソッドがいくつかあります。
move_left
move_right
move_up
move_down
code: python
from blessings import Terminal
term = Terminal()
print(term.move_up + 'Howdy!')
端末の高さと幅の取得
ターミナルの高さと幅を文字数で取得するのは簡単です。
code: python
from blessings import Terminal
term = Terminal()
heightさ = term.height
width = term.width
これらは要求されるたびに新しく更新されるので、SIGWINCHシグナル(端末のサイズが変更されたときに発行されるシグナル)で呼び出されるハンドラから使用しても安全に処理されます。
画面のクリア
Blessingsは、いくつかの画面クリア機能に対して構文上の糖を提供しています。
clear ー 画面全体をクリアする。
clear_eol ー 行末までクリアする。
clear_bol ー 行頭まで後退してクリアする。
clear_eos ー 画面の終わりまでクリアする。
code: python
print(term.clear())
フルスクリーンモード
エディタなどのフルスクリーンプログラムが、終了時に端末の以前の状態、例えば起動時のコマンドラインプロンプトを正確に復元するのを見たことがあるかもしれません。Curses ではこの動作を強制されますが、Blessings では任意です。もし、状態復元を行いた>い場合は、以下の機能を使用してください。
enter_fullscreen フルスクリーン出力が認可されたターミナルモードに切り替えます。出力を行う前にこれを印刷してください。
exit_fullscreen 通常モードに切り替え、enter_fullscreen が使われる前の状態を正確に復元します。exit_fullscreen を使用すると、プログラムの出力の痕跡をすべて消してしまうので、スクロールバックの中に何も残したくないときに使ってください。
また、ショートカットとして使えるコンテキストマネージャもあります。
code: python
from blessings import Terminal
term = Terminal()
with term.fullscreen():
# do print somthings...
withブロックで記述することで、簡潔に記述できるだけでなく、
例外が発生しても通常モードに戻るという利点もあります。
パイプ
プログラムがターミナルに接続されていない場合、たとえば他のコマンドにパイプされた
り、ファイルにリダイレクトされたりする場合、ターミナルのすべての制御属性は空の文
字列を返します。そのため、見栄えのよいファイルが得られるようになります。
参考
blessings
colorama
blessed
Curses for Windows