やってみる

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

Pythonのcursesを実行してみる

 cursesは端末を操作するためのライブラリである。メイン処理についてコードを書いてみた。

成果物

情報源

実行環境

環境 [ANSI Escape Code][] ライブラリ
bash echo -e "\e[31m赤\e[m" tput setaf 1 && echo '赤'
python print('\033[31m赤\033[m') import curses

 上記のように色をつけたりする。cursesというライブラリはこれをラップしてくれる。

最小コード

0

 なにもせず正常終了する。異常終了しない最小コードである。

#!/usr/bin/env python3
# coding: utf8
import os, curses
try:
    stdscr = curses.initscr()
    curses.start_color()
    curses.noecho()
    curses.cbreak()
    stdscr.keypad(True)
except Exception as e: raise
finally:
    curses.nocbreak()
    stdscr.keypad(False)
    curses.echo()
    curses.endwin()

1

 赤字REDを表示してみる。なにかキーを押下すると終了する。

#!/usr/bin/env python3
# coding: utf8
import os, curses
try:
    stdscr = curses.initscr()
    curses.start_color()
    curses.noecho()
    curses.cbreak()
    stdscr.keypad(True)

    curses.curs_set(0)
    curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK)
    stdscr.addstr('RED', curses.A_REVERSE | curses.color_pair(1))
    stdscr.getkey()
except Exception as e: raise
finally:
    curses.nocbreak()
    stdscr.keypad(False)
    curses.echo()
    curses.endwin()

2

 短い最小化コード。curses.wrapper()をつかって初期化やtry,exceptを簡略化する。

#!/usr/bin/env python3
# coding: utf8
import os, curses

def main(stdscr): pass

if __name__ == "__main__":
    curses.wrapper(main)

3

 引数を渡してみる。

#!/usr/bin/env python3
# coding: utf8
import os, curses

def main(stdscr, msg):
    stdscr.addstr(msg, curses.A_REVERSE | curses.color_pair(1))
    stdscr.getkey()


if __name__ == "__main__":
    curses.wrapper(main, 'Hello')

 引数は*args, **kwargsのどちらの形式でも渡せる。詳細はcurses.wrapper参照。

4

 クラスを渡してみる。__init__()が実行される。

#!/usr/bin/env python3
# coding: utf8
import os, curses

class Main:
    def __init__(self, screen):
        self.__screen = screen


if __name__ == "__main__":
    curses.wrapper(Main)

5

 クラスに引数を渡す。

#!/usr/bin/env python3
# coding: utf8
import os, curses

class Main:
    def __init__(self, screen, msg):
        self.__screen = screen


if __name__ == "__main__":
    curses.wrapper(Main, 'Hello')

6

 描画し、キー待受する。

#!/usr/bin/env python3
# coding: utf8
import os, curses

class Main:
    def __init__(self, screen, msg):
        self.__screen = screen
        self.__msg = msg
        self.__draw()
        self.__input()
    def __draw(self):
        self.__screen.addstr(self.__msg)
    def __input(self):
        self.__screen.getkey()


if __name__ == "__main__":
    curses.wrapper(Main, 'Hello')

7

 色の初期化をする。ついでにカーソル非表示。

#!/usr/bin/env python3
# coding: utf8
import os, curses

class Main:
    def __init__(self, screen, msg, color_index=1):
        self.__screen = screen
        self.__msg = msg
        self.__color_index = color_index
        self.__init_cursor()
        self.__init_color_pair()
        self.__draw()
        self.__input()
    def __init_cursor(self): curses.curs_set(0)
    def __init_color_pair(self):
        if not curses.has_colors(): raise Exception('このターミナルは色を表示できません。')
        if not curses.can_change_color(): raise Exception('このターミナルは色を変更できません。')
        curses.use_default_colors()
        for i in range(1, curses.COLORS):
            curses.init_pair(i, i, curses.COLOR_BLACK)
    def __draw(self):
        try:
            for i in range(1, curses.COLORS):
                self.__screen.addstr(str(i).rjust(3), curses.A_REVERSE | curses.color_pair(i))
        except curses.ERR: pass
        self.__screen.addstr(7, 0, self.__msg, curses.A_REVERSE | curses.color_pair(self.__color_index))
    def __input(self):
        self.__screen.getkey()


if __name__ == "__main__":
    curses.wrapper(Main, 'Hello', color_index=2)

 ポイントは以下。

  • curses.wrapper()で初期化を簡略化した
    • メイン関数にクラスを渡した
    • 位置引数、キーワード引数を渡した

f:id:ytyaru:20210609124509p:plain

対象環境

$ uname -a
Linux raspberrypi 5.4.83-v7l+ #1379 SMP Mon Dec 14 13:11:54 GMT 2020 armv7l GNU/Linux