1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

1 OverView

さて、Cursesであります。
あ、受け狙いじゃなくて、僕がElixirを理解するために、必要な経験だと思って書いております。

まずは、Cursesから紹介したいと思います。Cursesと呼んでますが、現在主流となっているのはncurses。

ncurses(new curses)は、ターミナルベースのユーザーインターフェースを作成するためのライブラリです。
もともとはSystem V Release 4.0(SVr4)のcursesライブラリのエミュレーションとして開発されましたが、
現在では多くの機能拡張が行われています

端末ベースのアプリ、特にvimやEmacsなどのテキストエディタでお世話になっていると思います。
https://invisible-island.net/ncurses/announce.html

見覚えあるUNIXのアプリケーション、多くないですか?

こいつをElixirから使得る様になるのが、ExNcursesです。

今回は、どういうものか?を先に書こうと思います。

回  内容
第一回 Elixirへのex_ncursesへのインストール説明
第二回 ElixirのAPIの説明
しなくてはなりません
第三回 Elixirで、スカッシュゲームを作ってみよう
第四回 ExNCursesのサンプルコード解説

2. 解説なんぞを。

2.1 まずは、ExNCursesの解説から。

最初に、一番ややこしいところを説明しましょう。読み飛ばしてくれて構いません。
ぶっちゃけ、後でわかるw

まずは、hexdocの引用から行きましょう。
https://hexdocs.pm/ex_ncurses/ExNcurses.html

ExNcurses lets Elixir programs create text-based user interfaces using ncurses.

ExNcursesは、Elixirプログラムがncursesを使用してテキストベースのユーザーインターフェースを作成できるようにします。

続いて、

Aside from keyboard input, ExNcurses looks almost like a straight translation of the C-based ncurses API. ExNcurses sends key events via messages. 

キーボード入力を除けば、ExNcursesはCベースのncurses APIのほぼ直訳のように見えます。ExNcursesはキーイベントをメッセージとして送信します。

「ExNcursesはCベースのncurses APIのほぼ直訳のように見えます」
ここが重要で、非常に簡単に、テキストベースのWindowを出すアプリケーションを構築出来ます。

また、「ExNcursesはキーイベントをメッセージとして送信します」と言う部分についてですが、これまた、簡単です。
画面に対して、キーが押された場合、

ハンドルするコードは、以下の様なものになります。 抜粋すると…

 # ターミナルからの入力を待ち受けます。ユーザーがキーを押すのを待ち、その入力を処理します。
 ExNcurses.listen()


 receive do
        # :ex_ncursesのプロセスから、イベントを受け取っている
        {:ex_ncurses, :key, key} ->
          handle_key(state, key)
 end


 # wasdそれぞれのキーをハンドルする、上記のhandle_keyと、関数の引数keyでパターンマッチングしている。
 defp handle_key(state, ?w), do: %{state | direction: :up}
 defp handle_key(state, ?a), do: %{state | direction: :left}
 defp handle_key(state, ?s), do: %{state | direction: :down}
 defp handle_key(state, ?d), do: %{state | direction: :right}

…これだけです。うん、これだけなんだ、「あ、Elixirの機能知らんと出来ないな」ってところは。

2.2 そしてサンプル…みたら驚くよ。

では、Hello worldから行きましょう。

Application.ensure_started(:ex_ncurses)

ExNcurses.initscr()

ExNcurses.mvprintw(4, 8, "Hello, 🐄\n")
ExNcurses.refresh()
ExNcurses.getch()
ExNcurses.endwin()

一行ずつ解説していきます。
ぶっちゃけ、Copilotに解説させた方が早いってくらいにシンプルです。

  1. Application.ensure_started(:ex_ncurses):

    この行は、:ex_ncurses アプリケーションが開始されていることを確認します。ライブラリを使用する前に初期化するために必要なステップです。
  2. ExNcurses.initscr():

    描画用の画面を初期化します。ExNcurses を使用する際に最初に呼び出す関数です。
  3. ExNcurses.mvprintw(4, 8, "Hello, 🐄\n"):

    この関数はカーソルを画面上の位置 (4, 8) に移動し、文字列 "Hello, 🐄\n" を表示します。座標 (4, 8) は画面上の行と列の位置を表します。
  4. ExNcurses.refresh():

    この関数は画面を更新して、行われた変更を反映させます。新しい内容を表示するためにこの関数を呼び出す必要があります。
  5. ExNcurses.getch():

    この関数はユーザーの入力(キー押下)を待ちます。プログラムを一時停止して、ユーザーがキーを押すのを待つ役割を果たします。
  6. ExNcurses.endwin():

    この関数は ncurses セッションを終了し、ターミナルを通常の状態に戻します。ncurses の使用が終わったら最後に呼び出す関数です。

くれぐれも1.のensure_startedを忘れない様にお願いします。
このプロセスが、Elixirのアプリケーションと、端末のキーの入力などを取り持ちます。

さて、ここからは本当に簡単、ExNcurses.initscr()で画面を初期化したら、その初期化した画面に対して、描画(上の例ではExNcurses.mvprintw)、描画を追えたら、ExNcurses.refresh/0で画面をリフレッシュしたら、画面に文字列が表示されます。

この、描画する関数を呼び出す -> 全部呼び出すのが終わったら、リフレッシュを言う流れを覚えてください。難しいのはここだけですね。

2.3 ウィンドウについて

Linuxの端末なのに、複数の画面に分かれてるアプリケーション、見たことないですな?
え?見たことない?ではEmacsを…とか言うと怒られるので、サンプルを実行してみましょう。

マルチ画面にする前に、まずは、端末の画面の中に、新しい画面を作成し、そこに対して"Hello, Window!"と描画してみましょう。

defmodule NcursesExample do
  def run do
    Application.ensure_started(:ex_ncurses)
    ExNcurses.initscr()

    win = ExNcurses.newwin(10, 20, 5, 5) # 新しいウィンドウの作成
    # winウィンドウ内のカーソル位置を(y, x)に移動します。これにより、次に描画される文字の位置が指定されます。
    ExNcurses.wmove(win, 1, 1)
    ExNcurses.waddstr(win, "Hello, Window!") # ウィンドウに文字列を表示
    ExNcurses.wrefresh(win)              # ウィンドウを更新
    ExNcurses.getch()                    # キー入力を待つ
    ExNcurses.delwin(win)                # ウィンドウを削除

    ExNcurses.endwin()
  end
end

NcursesExample.run()

表示する座標が変わってることに気づきでしょうか?

新しい関数を紹介しておきましょう。

ExNcurses.newwin(nlines, ncols, begin_y, begin_x)

説明: 新しいウィンドウを作成します。

パラメータ:

  • nlines: ウィンドウの行数
  • ncols: ウィンドウの列数
  • begin_y: ウィンドウの開始位置(y座標)
  • begin_x: ウィンドウの開始位置(x座標)

戻り値: 作成されたウィンドウのポインタ

ExNcurses.wmove(win, y, x)

説明: 指定したウィンドウ内でカーソルを新しい位置に移動します。

パラメータ:

  • win: ウィンドウのポインタ
  • y: 新しい行位置
  • x: 新しい列位置

戻り値: 成功した場合は0、失敗した場合はエラーコード

ExNcurses.wprintw(win, "Hello, Window!")

説明: 指定したウィンドウに文字列を書き込みます。

パラメータ:

  • win: ウィンドウのポインタ
  • str: 書き込む文字列

戻り値: 成功した場合は0、失敗した場合はエラーコード

これらの関数を使用することで、ex_ncursesライブラリを使ったウィンドウ操作が可能になります。詳細はこちらで確認できます。

では、お待ちかね、Windowを増やしてみましょう。

defmodule NcursesExample do
  def run do
    Application.ensure_started(:ex_ncurses)
    ExNcurses.initscr()

    win1 = ExNcurses.newwin(10, 20, 5, 5) # 新しいウィンドウの作成
    win2 = ExNcurses.newwin(10, 20, 5, 26) # 新しいウィンドウの作成
    # winウィンドウ内のカーソル位置を(y, x)に移動します。これにより、次に描画される文字の位置が指定されます。
    ExNcurses.wmove(win1, 1, 1)
    ExNcurses.wmove(win2, 1, 1)

    ExNcurses.waddstr(win1, "Hello, Window1!") # ウィンドウに文字列を表示
    ExNcurses.waddstr(win2, "Hello, Window2!") # ウィンドウに文字列を表示

    ExNcurses.wrefresh(win1)              # ウィンドウを更新
    ExNcurses.wrefresh(win2)              # ウィンドウを更新
    ExNcurses.getch()                    # キー入力を待つ
    ExNcurses.delwin(win1)                # ウィンドウを削除
    ExNcurses.delwin(win2)                # ウィンドウを削除

    ExNcurses.endwin()
  end
end

NcursesExample.run()

Windowsが二枚に増えましたね。
Hello, windows1とHello, windows2が別々のWindowsに「それぞれの座標に」描写されている
ことにご注意ください。

まとめ

さて、今回は端末への描写、Windowの作成をやってみました。
出来るのと便利は違う、と怒られそうなサンプルばかりになりましたね。

では、次回は「Elixirで、スカッシュゲームを作ってみよう」と題して、便利であることを
ごらんに入れたいと思います。

ほら、あれですよ!あれ!

「一週間待ってください、本物のEx_ncursesを御覧に入れますよ」

って山岡士郎がかっこつけるやつです。。。うん、がんばるね。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?