Curses

Curses とは仮想端末の画面を制御するために用意されたライブラリである。 一般的な出力メソッドでは仮想端末で下方向や右方向にしか文字列を出力できなかったが、Curses を使うと仮想端末の任意の場所に文字列を出力でき、さらに色なども変更できる。

大学の環境ではすぐに Curses を利用できる。

その他の環境で利用できない場合は、次のように gem でインストールする必要がある。

% gem install curses

基本の形式

Curses は以下の形のプログラムが基本となる。

#!/usr/koeki/bin/ruby
# -*- coding: utf-8 -*-
 
require "curses"
 
# Cursesの初期化
Curses.init_screen
 
begin
  <ここに処理を入れる>
ensure
  # Cursesの終了処理
  Curses.close_screen
end

プログラムの実行時に “warning: rb_safe_level will be removed in Ruby 3.0” と表示される場合は、次のように ruby にオプション “-W0” を付けて実行するとよい。

% ruby -W0 プログラム

メソッド

カーソルの移動

Curses.setpos(y, x)

仮想端末の画面の座標 (x, y) にカーソルを移動する。引数では y が先なので注意。

画面の行数は Curses.lines、列数は Curses.cols で分かる。

画面上の座標

文字の出力

Curses.addch(文字)

カーソルの位置に文字を出力する。

文字列の出力

Curses.addstr(文字列)

カーソルの位置に文字列を出力する。

画面表示の更新

Curses.refresh

Curses.addstr で文字列を出力をしても Curses.refresh を実行するまで画面に表示されない。

カーソルの表示/非表示

Curses.curs_set(番号)

カーソルを表示するには番号に 1、非表示にするには番号に 0 を入力する。

文字の読み込み

Curses.getch

標準入力から1文字読み込む。 いわゆるキー入力である。


色を使う

色を使うにはまず、Cursor.start_color を実行する。

Cursor.start_color

カラーペアの設定

Curses.init_pair(カラーペア番号, 文字の色番号, 背景の色番号)

色を使うための準備として Curses.init_pair で文字と背景の色のペアをカラーペア番号(1以上の任意の整数)に設定する必要がある。 色番号は Curses::COLOR_BLUECurses::COLOR_BLACK などで指定するとよい。

色をつける

Curses.attrset(Curses.color_pair(カラーペア番号))

文字に色をつけて出力するには、文字の出力前にカラーペア番号から選択する。

プログラム例

プログラム例1

プログラム curses1.rb は仮想端末の画面の四隅と中央に文字を出力する。

curses1.rb
  1. #!/usr/koeki/bin/ruby
  2. # -*- coding: utf-8 -*-
  3.  
  4. require "curses"
  5.  
  6. # Cursesの初期化
  7. Curses.init_screen
  8.  
  9. begin
  10. # 左上に"A"を出力
  11. Curses.setpos(0, 0)
  12. Curses.addch("A")
  13.  
  14. # 右上に"B"を出力
  15. Curses.setpos(0, Curses.cols - 1)
  16. Curses.addch("B")
  17.  
  18. # 左下に"C"を出力
  19. Curses.setpos(Curses.lines - 1, 0)
  20. Curses.addch("C")
  21.  
  22. # 右下に"D"を出力
  23. Curses.setpos(Curses.lines - 1, Curses.cols - 1)
  24. Curses.addch("D")
  25.  
  26. # 中央に"O"を出力
  27. Curses.setpos(Curses.lines / 2, Curses.cols / 2)
  28. Curses.addch("O")
  29.  
  30. # 画面表示を更新
  31. Curses.refresh
  32.  
  33. # キー入力があるまで待つ
  34. Curses.getch
  35.  
  36. ensure
  37. # Cursesの終了処理
  38. Curses.close_screen
  39. end

プログラム例2

プログラム curses2.rb は文字と背景の色を変えながら文字列を出力する。

curses2.rb
  1. #!/usr/koeki/bin/ruby
  2. # -*- coding: utf-8 -*-
  3.  
  4. require "curses"
  5.  
  6. # Cursesの初期化
  7. Curses.init_screen
  8.  
  9. begin
  10. # 色の使用開始
  11. Curses.start_color
  12.  
  13. # カラーペア番号を設定
  14. # 背景色を黒
  15. Curses.init_pair( 1, Curses::COLOR_BLUE, Curses::COLOR_BLACK)
  16. Curses.init_pair( 2, Curses::COLOR_CYAN, Curses::COLOR_BLACK)
  17. Curses.init_pair( 3, Curses::COLOR_GREEN, Curses::COLOR_BLACK)
  18. Curses.init_pair( 4, Curses::COLOR_MAGENTA, Curses::COLOR_BLACK)
  19. Curses.init_pair( 5, Curses::COLOR_RED, Curses::COLOR_BLACK)
  20. Curses.init_pair( 6, Curses::COLOR_WHITE, Curses::COLOR_BLACK)
  21. Curses.init_pair( 7, Curses::COLOR_YELLOW, Curses::COLOR_BLACK)
  22. # 文字色を黒
  23. Curses.init_pair( 8, Curses::COLOR_BLACK, Curses::COLOR_BLUE)
  24. Curses.init_pair( 9, Curses::COLOR_BLACK, Curses::COLOR_CYAN)
  25. Curses.init_pair(10, Curses::COLOR_BLACK, Curses::COLOR_GREEN)
  26. Curses.init_pair(11, Curses::COLOR_BLACK, Curses::COLOR_MAGENTA)
  27. Curses.init_pair(12, Curses::COLOR_BLACK, Curses::COLOR_RED)
  28. Curses.init_pair(13, Curses::COLOR_BLACK, Curses::COLOR_WHITE)
  29. Curses.init_pair(14, Curses::COLOR_BLACK, Curses::COLOR_YELLOW)
  30.  
  31. # カラーペア番号で順に処理
  32. 1.upto(14) do |i|
  33. # 文字の色をセット
  34. Curses.attrset(Curses.color_pair(i))
  35.  
  36. # 文字列を出力
  37. Curses.setpos(i, 0)
  38. Curses.addstr(sprintf("カラーペア番号 %d", i))
  39. end
  40.  
  41. # 画面表示を更新
  42. Curses.refresh
  43.  
  44. # キー入力があるまで待つ
  45. Curses.getch
  46.  
  47. ensure
  48. # Cursesの終了処理
  49. Curses.close_screen
  50. end

プログラム例3

プログラム curses3.rb はカーソルキーで “x” を移動する。 他のキーを押すと終了する。

curses3.rb
  1. #!/usr/koeki/bin/ruby
  2. # -*- coding: utf-8 -*-
  3.  
  4. require "curses"
  5.  
  6. # Cursesの初期化
  7. Curses.init_screen
  8.  
  9. begin
  10. # 初期座標
  11. x = y = 0
  12.  
  13. # カーソルを非表示
  14. Curses.curs_set(0)
  15.  
  16. # 入力文字を非表示
  17. Curses.noecho
  18.  
  19. # キーパッドを有効にする
  20. Curses.stdscr.keypad(true)
  21.  
  22. # Enterキーが押されるまでループ
  23. while 1
  24. # (x, y) に文字を出力
  25. Curses.setpos(y, x)
  26. Curses.addch("x")
  27.  
  28. # 画面表示を更新
  29. Curses.refresh
  30.  
  31. # キー入力があるまで待つ
  32. c = Curses.getch
  33.  
  34. # (x, y) の文字を削除
  35. Curses.setpos(y, x)
  36. Curses.delch
  37.  
  38. # キー判定
  39. case c
  40. when Curses::KEY_UP # 「↑」キー
  41. # 一番上の行でなければ上に移動
  42. if y > 0
  43. y -= 1
  44. end
  45. when Curses::KEY_DOWN # 「↓」キー
  46. # 一番下の行でなければ下に移動
  47. if y < Curses.lines - 1
  48. y += 1
  49. end
  50. when Curses::KEY_RIGHT # 「→」キー
  51. # 一番右の列でなければ右に移動
  52. if x < Curses.cols - 1
  53. x += 1
  54. end
  55. when Curses::KEY_LEFT # 「←」キー
  56. # 一番左の列でなければ左に移動
  57. if x > 0
  58. x -= 1
  59. end
  60. else
  61. # 他のキーでループを抜ける
  62. break
  63. end
  64. end
  65.  
  66. ensure
  67. # Cursesの終了処理
  68. Curses.close_screen
  69. end