From 6a924f2f1afd973f8cb23208a17e707c9b055a5c Mon Sep 17 00:00:00 2001 From: Dave Lucia Date: Wed, 6 Mar 2024 21:16:29 -0500 Subject: [PATCH 1/2] Start writing some module docs --- README.md | 37 ++++++++++++++++++++++++++++++++++++- lib/lua.ex | 8 +++++--- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e239d4a..5f2a89e 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,43 @@ # Lua -Brings all the expected UX of Elixir to Luerl + + +Lua is an ergonomic interface to [Luerl](https://github.com/rvirding/luerl), aiming to be the best way to use Luerl from Elixir. + +## Features * Ergonomic API for Elixir <> Lua FFI * Improved error messages * Deep-setting variables and state * Excellent documentation and guides for working with Luerl + +## Usage + +### Executing Lua + +Lua can be run using the `eval!/2` function + +``` elixir + iex> {[4], _} = + ...> Lua.eval!(""" + ...> return 2 + 2 + ...> """) + +``` + +### Exposing Elixir functions to Lua + +`Lua` provides the `deflua` macro for exposing Elixir functions to Lua + + defmodule MyAPI do + use Lua.API + + deflua double(v), do: 2 * v + end + + lua = Lua.new() |> Lua.inject_module(MyAPI) + + {[10], _} = + Lua.eval!(lua, """ + return double(5) + """) diff --git a/lib/lua.ex b/lib/lua.ex index f90744a..3d59d63 100644 --- a/lib/lua.ex +++ b/lib/lua.ex @@ -1,7 +1,9 @@ defmodule Lua do - @moduledoc """ - Lua aims to be the best way to integrate Luerl into an Elixir project. - """ + @external_resource "README.md" + @moduledoc @external_resource + |> File.read!() + |> String.split("") + |> Enum.fetch!(1) defstruct [:state, functions: %{}] From 5ea04f55cd2501b55af1868d8886b141ac9ec6db Mon Sep 17 00:00:00 2001 From: Dave Lucia Date: Wed, 6 Mar 2024 21:20:38 -0500 Subject: [PATCH 2/2] cleanup --- README.md | 2 +- lib/lua.ex | 4 ++-- test/lua/api_test.exs | 4 ++-- test/lua_test.exs | 14 +++++++------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 5f2a89e..76b0d3d 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Lua can be run using the `eval!/2` function deflua double(v), do: 2 * v end - lua = Lua.new() |> Lua.inject_module(MyAPI) + lua = Lua.new() |> Lua.load_api(MyAPI) {[10], _} = Lua.eval!(lua, """ diff --git a/lib/lua.ex b/lib/lua.ex index 3d59d63..fdac960 100644 --- a/lib/lua.ex +++ b/lib/lua.ex @@ -220,9 +220,9 @@ defmodule Lua do Inject functions written with the `deflua` macro into the Lua runtime """ - # TODO rename to load_api - def inject_module(lua, module, scope \\ []) do + def load_api(lua, module, scope \\ nil) do funcs = :functions |> module.__info__() |> Enum.group_by(&elem(&1, 0), &elem(&1, 1)) + scope = scope || module.scope() module.__lua_functions__() |> Enum.reduce(lua, fn {name, with_state?, variadic?}, lua -> diff --git a/test/lua/api_test.exs b/test/lua/api_test.exs index b10b4ed..507bbab 100644 --- a/test/lua/api_test.exs +++ b/test/lua/api_test.exs @@ -16,7 +16,7 @@ defmodule Lua.APITest do end """) - lua = Lua.inject_module(Lua.new(), module, module.scope()) + lua = Lua.load_api(Lua.new(), module) assert {["Whoa, check this out!"], _} = Lua.eval!(lua, """ @@ -41,7 +41,7 @@ defmodule Lua.APITest do end """) - lua = Lua.inject_module(Lua.new(), module, module.scope()) + lua = Lua.load_api(Lua.new(), module) assert {["starting value", 111], _} = Lua.eval!(lua, """ diff --git a/test/lua_test.exs b/test/lua_test.exs index 2d6d001..f1a7605 100644 --- a/test/lua_test.exs +++ b/test/lua_test.exs @@ -238,7 +238,7 @@ defmodule LuaTest do end end - lua = Lua.inject_module(Lua.new(), Test, Test.scope()) + lua = Lua.load_api(Lua.new(), Test) error = "Lua runtime error: test.foo() failed, expected 1 arguments, got 2" @@ -278,7 +278,7 @@ defmodule LuaTest do end end - describe "inject_module/2 and inject_module/3" do + describe "load_api/2 and load_api/3" do defmodule TestModule do use Lua.API @@ -297,22 +297,22 @@ defmodule LuaTest do end test "injects a global Elixir module functions into the Lua runtime", %{lua: lua} do - lua = Lua.inject_module(lua, TestModule) + lua = Lua.load_api(lua, TestModule) assert {["test"], _} = Lua.eval!(lua, "return foo('test')") end test "injects a scoped Elixir module functions into the Lua runtime", %{lua: lua} do - lua = Lua.inject_module(lua, TestModule, ["scope"]) + lua = Lua.load_api(lua, TestModule, ["scope"]) assert {["test"], _} = Lua.eval!(lua, "return scope.foo('test')") end test "inject a variadic function", %{lua: lua} do - lua = Lua.inject_module(lua, TestModule, ["scope"]) + lua = Lua.load_api(lua, TestModule, ["scope"]) assert {["a-b-c"], _} = Lua.eval!(lua, "return scope.bar('a', 'b', 'c')") end test "injects Elixir functions that have multiple arities", %{lua: lua} do - lua = Lua.inject_module(lua, TestModule, ["scope"]) + lua = Lua.load_api(lua, TestModule, ["scope"]) assert {["a default"], _} = Lua.eval!(lua, "return scope.test(\"a\")") assert {["a b"], _} = Lua.eval!(lua, "return scope.test(\"a\", \"b\")") @@ -369,7 +369,7 @@ defmodule LuaTest do end setup do - %{lua: Lua.new() |> Lua.inject_module(Examples, ["example"])} + %{lua: Lua.new() |> Lua.load_api(Examples, ["example"])} end test "can work with numbers", %{lua: lua} do