~tomterl/public-inbox

This thread contains a patchset. You're looking at the original emails, but you may wish to use the patch review UI. Review patch

[PATCH thp] New module: +lua

Carlos Une <une@fastmail.fm>
Details
Message ID
<20240718005230.4603-1-une@fastmail.fm>
DKIM signature
pass
Download raw message
Patch: +157 -4
---
 Makefile        |  2 ++
 README.org      |  8 ++---
 lua/lua.ha      | 56 ++++++++++++++++++++++++++++++
 man/thp.5.scd   |  4 +++
 mods/lua+lua.ha | 91 +++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 157 insertions(+), 4 deletions(-)
 create mode 100644 lua/lua.ha
 create mode 100644 mods/lua+lua.ha

diff --git a/Makefile b/Makefile
index a2bc2e9..626eb09 100644
--- a/Makefile
+++ b/Makefile
@@ -13,11 +13,13 @@ MANDIR := $(PREFIX)/share/man
DESTDIR :=

GITLIBS = $(patsubst -pthread,,$(shell $(PKG_CONFIG) --libs libgit2 --static))
LUALIBS = $(shell $(PKG_CONFIG) --libs lua5.4)

HAREPATH := ./vendor:${HAREPATH}

MODS ?= host path sigil $(EXTRA_MODS)
THPD_LIBS = $(if $(filter git,$(MODS)),$(GITLIBS))
THPD_LIBS+= $(if $(filter lua,$(MODS)),$(LUALIBS))
THPD_EXTRA_DEPS =$(if $(filter git,$(MODS)),git/*.ha) $(if $(filter timer,$(MODS)),timer/*.ha)

all: thpd thp docs
diff --git a/README.org b/README.org
index 5dc7400..d303802 100644
--- a/README.org
+++ b/README.org
@@ -29,16 +29,16 @@ You need ~hare~, follow the instructions [[https://harelang.org/installation][at
To build thp with all modules included, you need libgit2 and your platforms libgit2-dev equivalent installed, then issued

#+BEGIN_SRC sh :exports code
make EXTRA_MODS="project git clock timer shind uptime moon sun star"
make EXTRA_MODS="project git clock timer shind uptime moon sun star" test
make EXTRA_MODS="project git clock timer shind uptime moon sun star lua"
make EXTRA_MODS="project git clock timer shind uptime moon sun star lua" test
make PREFIX="${HOME}" install
#+END_SRC

To build with just the modules you use in your spec, use ~MODS~:

#+BEGIN_SRC sh :exports code
make MODS="path host project timer uptime moon sun star"
make MODS="path host project timer uptime moon sun star" test
make MODS="path host project timer uptime moon sun star lua"
make MODS="path host project timer uptime moon sun star lua" test
make PREFIX="${HOME}" install
#+END_SRC

diff --git a/lua/lua.ha b/lua/lua.ha
new file mode 100644
index 0000000..190faba
--- /dev/null
+++ b/lua/lua.ha
@@ -0,0 +1,56 @@
// Author: Carlos Une <une@fastmail.fm>
// Maintainer: Carlos Une <une@fastmail.fm>
//
// SPDX-FileCopyrightText:  2024 Carlos Une <une@fastmail.fm>
// SPDX-License-Identifier: GPL-3.0-or-later
use types::c;

export type KContext = c::ptrdiff;
export type KFunction = nullable *opaque;
export type State = opaque;
export type Integer = int;
export def MULTRET: int = -1;
export def OK: int = 0;

export fn tostring(L: *State, i: int) *const c::char = {
	return tolstring(L, i, null);
};

export fn pop(L: *State, n: int) void = settop(L, -(n)-1);

export fn loadfile(L: *State, filename: *const c::char) int = {
	return loadfilex(L, filename, null);
};

export fn pcall(L: *State, nargs: int, nresults: int, msgh: int) int = {
	return pcallk(L, nargs, nresults, msgh, 0, null);
};

export fn dofile(L: *State, filename: *const c::char) int = {
	let l = loadfilex(L, filename, null);
	return if (l != 0) l else pcall(L, 0, MULTRET, 0);
};

export @symbol("luaL_newstate") fn newstate() *State;
export @symbol("luaL_openlibs") fn openlibs(L: *State) void;
export @symbol("luaL_loadstring") fn loadstring(L: *State,
	s: *const c::char) int;
export @symbol("lua_pcallk") fn pcallk(L: *State, nargs: int, nresults: int,
	msgh: int, ctx: KContext, k: KFunction) int;
export @symbol("lua_close") fn close(L: *State) void;
export @symbol("luaL_loadfilex") fn loadfilex(L: *State,
	filename: nullable *const c::char, mode: nullable *const c::char) int;
export @symbol("lua_createtable") fn createtable(L: *State, narr: int,
	nrec: int) void;
export @symbol("lua_pushstring") fn pushstring(L: *State,
	s: *const c::char) *const c::char;
export @symbol("lua_pushboolean") fn pushboolean(L: *State, int) void;
export @symbol("lua_pushinteger") fn pushinteger(L: *State, n: Integer) void;
export @symbol("lua_setglobal") fn setglobal(L: *State,
	name: *const c::char) void;
export @symbol("lua_settable") fn settable(L: *State, idx: int) void;
export @symbol("lua_isstring") fn isstring(L: *State, idx: int) int;
export @symbol("lua_gettop") fn gettop(L: *State) int;
export @symbol("lua_settop") fn settop(L: *State, n: int) void;
export @symbol("lua_tolstring") fn tolstring(L: *State, n: int,
	sz: nullable *size) *const c::char;
diff --git a/man/thp.5.scd b/man/thp.5.scd
index 5b3450a..0a94375 100644
--- a/man/thp.5.scd
+++ b/man/thp.5.scd
@@ -123,6 +123,10 @@ the modules configuration settings.
  The location and time format can be configured. See thpd(5).
- *star*++
  displays the position of a star as seen by an observer on Earth.
- *lua*++
  Runs a Lua script —_XDG_DATA_HOME_/thp/thp.lua — and copies its return value
  to the prompt string. The script has read-only access to thp's internal
  _env::env_ struct through a Lua table named _thp.env_.

# STYLES

diff --git a/mods/lua+lua.ha b/mods/lua+lua.ha
new file mode 100644
index 0000000..709bc38
--- /dev/null
+++ b/mods/lua+lua.ha
@@ -0,0 +1,91 @@
// Author: Carlos Une <une@fastmail.fm>
// Maintainer: Carlos Une <une@fastmail.fm>
//
// SPDX-FileCopyrightText:  2024 Carlos Une <une@fastmail.fm>
// SPDX-License-Identifier: GPL-3.0-or-later
use env;
use dirs;
use strings;
use types::c;
use lua;

@init fn register_lua() void = {
	register("lua", &mod_lua);
};

fn mkfield(L: *lua::State, k: str, v: (str | bool | uint)) void = {
	pushstring(L, k);
	match (v) {
	case let x: str =>
		pushstring(L, x);
	case let x: bool =>
		lua::pushboolean(L, if (x) 1 else 0);
	case let x: uint =>
		lua::pushinteger(L, x: int);
	};
	lua::settable(L, -3);
};

fn pushstring(L: *lua::State, s: str) void = {
	let string = c::fromstr(s);
	defer free(string);
	lua::pushstring(L, string);
};

export fn mod_lua(pe: *env::env) str = {
	let L = lua::newstate();
	defer lua::close(L);

	lua::openlibs(L);
	lua::createtable(L, 0, 0);
	pushstring(L, "env");
	lua::createtable(L, 0, 0);
	pushstring(L, "control");
	lua::createtable(L, 0, 0);
	mkfield(L, "remote", pe.control.remote);
	mkfield(L, "zsh", pe.control.zsh);
	mkfield(L, "bash", pe.control.bash);
	mkfield(L, "exit", pe.control.exit);
	mkfield(L, "reload", pe.control.reload);
	mkfield(L, "timer", pe.control.timer);
	mkfield(L, "root", pe.control.root);
	mkfield(L, "wtitle", pe.control.wtitle);
	lua::settable(L, -3);
	mkfield(L, "home", pe.home);
	mkfield(L, "columns", pe.columns);
	mkfield(L, "user", pe.user);
	mkfield(L, "host", pe.host);
	mkfield(L, "pwd", pe.pwd);
	mkfield(L, "pd", pe.pd);
	mkfield(L, "cid", pe.cid);
	lua::settable(L, -3);

	let thp = c::fromstr("thp");
	defer free(thp);
	lua::setglobal(L, thp);

	let script = strings::concat(dirs::data("thp"), "/thp.lua");
	defer free(script);

	let scriptz = c::fromstr(script);
	defer free(scriptz);

	if (lua::dofile(L, scriptz) != lua::OK) {
		let errormsg = lua::tostring(L, -1);
		lua::pop(L, 1);
		return strings::concat("mod_lua:", c::tostr(errormsg)!);
	};

	if (lua::gettop(L) != 1) {
		return strings::dup("mod_lua:script must return a value.");
	};

	if (lua::isstring(L, -1) == 0) {
		lua::pop(L, 1);
		return strings::dup("mod_lua:script must return a string.");
	};

	let r = lua::tostring(L, -1);
	lua::pop(L, 1);
	return strings::dup(c::tostr(r)!);
};
-- 
2.39.2
Reply to thread Export thread (mbox)