やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Pythonで標準TUIライブラリcursesを使ってみた

テキストと色の表示確認ができた。

成果物

github.com

f:id:ytyaru:20180416154529p:plainf:id:ytyaru:20180416154533p:plainf:id:ytyaru:20180416154543p:plain

背景

rangerを使ってみてTUIに興味を持った。GUIよりも簡単かつ軽量。

ソースコード

0.py

Hello curses !!と表示するだけ。なのに非常に長い。

import curses
# 初期化
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
stdscr.keypad(True)
curses.curs_set(0)

stdscr.clear()
stdscr.addstr(0, 0, 'Hello curses !!')
stdscr.refresh()
stdscr.getkey()

# 終了処理
curses.nocbreak()
stdscr.keypad(False)
curses.echo()
curses.endwin()

f:id:ytyaru:20180416154529p:plain

1.py

curses.wrapper()で初期&終了の処理を簡略化。

import curses
def main(stdscr):
    stdscr.clear()
    stdscr.addstr(0, 0, 'Hello curses !!')
    stdscr.addstr(1, 0, 'Next Line.')
    stdscr.addstr(2, 4, 'Indent.')
    stdscr.refresh()
    stdscr.getkey()
curses.wrapper(main)

f:id:ytyaru:20180416154533p:plain

じつは終了処理ができずに異常終了してしまうと、その後のターミナルの表示がグチャグチャに壊れる。

異常終了したときに端末がめちゃめちゃになる

これを回避するためにcurses.wrapper()必須。そのせいでコードが見づらくなってしまう。

なぜwith句にしてくれなかったのか。

error.py

わざと壊してみた結果が以下。

f:id:ytyaru:20180416160509p:plain

Enterキーを押下してみると、改行コードが表示されない。

f:id:ytyaru:20180416160514p:plain

終了処理を実行する前にraise Exception()すれば再現できる。

2.py

256色の表示。

ターミナルはRaspbianに入っていたLXTerminal 0.2.0

f:id:ytyaru:20180416154543p:plain

import os, curses
def main(stdscr):
    if not curses.has_colors(): raise Exception('このターミナルは色を表示できません。')
    stdscr.clear()
    curses.start_color()
    curses.use_default_colors()
    for i in range(0, curses.COLORS):
        curses.init_pair(i + 1, i, -1)
    try:
        for i in range(0, 255):
            stdscr.addstr(str(i), curses.color_pair(i))
    except curses.ERR: pass
    stdscr.refresh()
    stdscr.getkey()

os.environ['TERM'] = 'xterm-256color'
curses.wrapper(main)

環境変数TERMxterm-256colorを指定することで256色使えるようにしている。

shellでは以下のコード。

$ export TERM='xterm-256color'

echoで確認。

$ echo $TERM
xterm-256color

細かいメソッドなどについてはドキュメントを参照。(翻訳がぜんぜんできていないので読むのに苦労する)

開発環境

参考