utopのプロンプトはUTop.prompt
を介してカスタマイズすることができます。
utop # UTop.prompt;;
- : LTerm_text.t React.signal ref = {Pervasives.contents = <abstr>}
何だこれは・・・
文字列じゃダメなのか?
プロンプトごときのためにドキュメント読みたくねーよ
などと思われるのはもっともですが、例を見ていただければそれほど煩雑でないことが分かってもらえるかと思います。それどころか
- 型がつく!
- REPLで開発できる!
と思えばむしろ楽しいくらいです。
ちなみにLTerm_text.t
とReact.signal
はそれぞれターミナル操作のためのライブラリであるLambda-Term
とFRPライブラリのReact
から来ています。
以下では例を挙げて説明しますが、私はそれぞれのライブラリ(特にReact
)の使い方をちゃんと理解していないので、下手な書き方になっているかも知れません。
その前に
utopはいくつかプロンプトをディレクティブの形で用意してくれています。ぜひチェックしてみてください。
#utop_prompt_dummy
#utop_prompt_fancy_dark
#utop_prompt_fancy_light
#utop_prompt_simple
シンプルなプロンプト
デフォルトのプロンプトは派手なので、シンプルにutop #
とだけ表示するようにしてみましょう。色も一色だけにします。
# require "lambda-term";;
let open LTerm_text in
UTop.prompt :=
[B_fg (LTerm_style.rgb 191 255 0); S "utop # "]
|> eval
|> React.S.const
;;
各要素の型を確認してみます。
utop # [B_fg (LTerm_style.rgb 191 255 0); S "utop # "];;
- : item list = [B_fg (LTerm_style.RGB (191, 255, 0)); S "utop # "]
utop # LTerm_style.rgb;;
- : int -> int -> int -> LTerm_style.color = <fun>
utop # eval;;
- : markup -> t = <fun>
utop # React.S.const;;
- : 'a -> 'a React.signal = <fun>
詳しく言うとB_fg
とS
はitem
型のコンストラクタで、前者はLTerm_style.color
を受け取って文字色を指定し、後者は文字列を指定するものです。これ以外のコンストラクタについてはドキュメントをご覧ください。
またmarkup = item list
です。
これだけ見れば使い方も大体分かってしまったかと思います。
動的なプロンプト
プロンプトの表示ごとに内容を変更することもできます。個人的にはここでどう書けばいいのか悩みました。動的に内容を変更するならunit -> 'a
を用意してやれば良さそうですが、代わりにここではReact
の仕組みに頼ることになります。
プロンプトとして<ユーザー名>@<カレントディレクトリ> #
を表示してみましょう。
let open LTerm_text in
let make_prompt (c : int) =
eval [S (Printf.sprintf "%s@%s # " (Sys.getenv_exn "LOGNAME") (Sys.getcwd ()))] in
UTop.prompt := React.S.l1 make_prompt UTop.count
;;
React.S.l1
とUTop.count
の型を見てみます。
utop # React.S.l1;;
- : ?eq:('b -> 'b -> bool) -> ('a -> 'b) -> 'a React.signal -> 'b React.signal
= <fun>
utop # UTop.count;;
- : int React.signal = <abstr>
React.S.l1
はその名の通り1引数関数を受け取ります。そのような関数がl6
まで用意されています。またUTop.count
の中身は、プロンプトが表示されるごとに1だけ加増されます。このカウント値をmake_prompt
の中で使っていないので奇妙に見えますが、こうしないとプロンプトが更新されません。この辺りの理由をうまく説明できないのは私の力不足のせいです。
まとめ
何となくでも使い方が分かっていただけたでしょうか。残念ながらこの記事を書いている時点では情報がほとんどないようです。ライブラリのドキュメント以外ではutopのソースが理解の助けになりました。
utop/uTop.ml at master · diml/utop · GitHub
LTerm_style (lambda-term.LTerm_style)
LTerm_text (lambda-term.LTerm_text)
React.S