この記事は、Elixir Advent Calendar 2023 シリーズ12 の20日目です
piacere です、ご覧いただいてありがとございます
今回も、前回に引き続き、下記の追体験 … つまり「Livebookの改造」をするコラムで、今回は、Elixirコードを実行できる「Livebookコードブロック」についてハックしていきます
たった1時間の短時間で、
— piacere @ Elixir/D2C/xR+メイドコスプレでデジタルから現実改変する49歳 (@piacere_ex) September 26, 2023
・Livebookホーム画面
・ユーザー設定
・セッション(起動されたNotebookのこと)
・コードエディタ部分
・コード実行部分
のハックや改造ができました😆 #LiveViewJP
今回、初めてLivebookハックしてみましたが、いつものElixirらしく読みやすいコードでハッピーでした😍 pic.twitter.com/EhohlbKTmA
みんなでコードを眺めて、震えて、納涼するイベント、LiveViewJP#21「Livebookコードを眺めてみんなで震えて納涼する会」 のコラム版です
ちな、私もマトモにLivebookコードを読んだことが無かったので、会が成立しない位、グダグダになったらゴメンナサイ … と予め謝った上で開催しました
来月の #LiveViewJP は、Elixirに素晴らしいWeb上開発体験を提供している「Livebook」のコードハック会😜https://t.co/tlHSq67Wmg
— piacere @ Elixir/D2C/xR+メイドコスプレでデジタルから現実改変する49歳 (@piacere_ex) August 25, 2023
みんなでコードを眺めて、震えて、納涼しましょう🤣
ちな私もマトモに読んだこと無いので、会が成立しない位、グダグダになったらゴメンナサイ…と予め謝っておく😋
結果的には、新たなLiveViewデバッグ機能も使い倒す、ステキなElixir printfデバッグ(正確にはIO.inspectだがw)のシェア会になりましたので、その一端をコラムでも共有します 😋
あと、このコラムが、面白かったり、役に立ったら、 をお願いします
Elixirコードを実行できる「Livebookコードブロック」
実は、Elixir標準モジュールの仕様を知っていると、ここはクイックハックできます
Code
モジュールには、下記のようなElixirコードを実行し、その結果を返す関数があるので、これで当たりを付けていきます
Code.eval_file
Code.eval_string
eval_quoted
eval_quoted_with_env
お、eval_quoted_with_env
付近が何か匂います … 関数も eval
ですし
printfデバッグを仕掛けて、合ってるか確認してみましょう
…
defp eval(:elixir, code, binding, env) do
+IO.puts "=========== eval ==========="
+IO.inspect code
+IO.puts "=========== eval ==========="
{{result, extra_diagnostics}, diagnostics} =
Code.with_diagnostics([log: true], fn ->
try do
…
Livebookのこの箇所に IO.puts
や IO.inspect
を仕掛けると、Livebook上で表示されるのですね
Livebookコードブロックの情報を取得する
コードブロックの実行部分が特定できたので、何か改造を施してみましょう
その前に、このコード実行評価でどのような値を返却しているのか見てみます
…
defp eval(:elixir, code, binding, env) do
…
|> case do
{:ok, value, binding, env} ->
+IO.puts "=========== eval ==========="
+IO.inspect value
+IO.inspect binding
+IO.inspect env
+IO.puts "=========== eval ==========="
{{:ok, value, binding, env}, []}
…
なるほど、実行結果と、謎の binding
、そしてコンパイル時の実行環境情報を保持する Macro.Env
が返されているようです
env
から、下記のようにコードのロケーション情報を拾ってみましょう
…
defp eval(:elixir, code, binding, env) do
…
|> case do
{:ok, value, binding, env} ->
IO.puts "=========== eval ==========="
IO.inspect value
IO.inspect binding
+IO.inspect env |> Macro.Env.location
IO.puts "=========== eval ==========="
{{:ok, value, binding, env}, []}
…
value
がリストのときは、セル情報を載せて、返してみましょう
…
defp eval(:elixir, code, binding, env) do
…
|> case do
{:ok, value, binding, env} ->
-IO.puts "=========== eval ==========="
-IO.inspect value
-IO.inspect binding
-IO.inspect env |> Macro.Env.location
-IO.puts "=========== eval ==========="
- {{:ok, value, binding, env}, []}
+ case value do
+ value when is_list(value) -> {{:ok, value ++ "location: #{Keyword.get(env |> Macro.Env.location, :file)}", binding, env}, []}
+ _ -> {{:ok, value, binding, env}, []}
+ end
…
終わりに
Livebookコードブロックのハックをしましたが、簡単でしたよね?
Elixirの知識があれば、OSSをハックしやすいということが伝われば幸いです
次回は、Livebookをノーコードたらしめる重要機能である「SmartCell」付近を攻略していきます