Elua: initial commit

Elua is a LuaJIT based runtime for the EFL meant to provide facilities for rapid application development. The name is temporary. The EFL bindings will be generated with Eolian. @feature
This commit is contained in:
Daniel Kolesa 2014-04-03 16:01:01 +01:00 committed by Daniel Kolesa
parent 3e81b73aa8
commit 832f652a5a
10 changed files with 885 additions and 1 deletions

View File

@ -4307,6 +4307,51 @@ EFL_EVAL_PKGS([ETHUMB_CLIENT])
EFL_LIB_END_OPTIONAL([Ethumb_Client])
#### End of Ethumb_Client
#### Elua
have_elua="yes"
if test "${want_lua_old}" = "yes"; then
have_elua="no"
fi
EFL_LIB_START_OPTIONAL([Elua], [test "${have_elua}" = "yes"])
### Default values
AM_CONDITIONAL([HAVE_ELUA], [test "x${have_elua}" = "xyes"])
### Additional options to configure
### Checks for programs
## Compatibility layers
EFL_PLATFORM_DEPEND([ELUA], [evil])
### Checks for libraries
EFL_INTERNAL_DEPEND_PKG([ELUA], [eina])
EFL_INTERNAL_DEPEND_PKG([ELUA], [eo])
EFL_INTERNAL_DEPEND_PKG([ELUA], [ecore])
EFL_DEPEND_PKG([ELUA], [LUAJIT], [luajit >= 2.0.0])
EFL_EVAL_PKGS([ELUA])
### Checks for header files
### Checks for types
### Checks for structures
### Checks for compiler characteristics
### Checks for linker characteristics
### Checks for library functions
### Check availability
EFL_LIB_END_OPTIONAL([Elua])
#### End of Elua
AC_ARG_ENABLE([always-build-examples],
[AC_HELP_STRING([--enable-always-build-examples],
@ -4567,6 +4612,7 @@ echo "Edje............: ${efl_lib_optional_edje} (${features_edje})"
echo "Emotion.........: ${efl_lib_optional_emotion} (${features_emotion})"
echo "Ethumb..........: ${efl_lib_optional_ethumb}"
echo "Ethumb_Client...: ${efl_lib_optional_ethumb_client}"
echo "Elua............: $have_elua"
if test "${build_tests}" = "none"; then
echo "Tests...........: no"
elif test "${build_tests}" = "auto"; then

View File

@ -79,6 +79,8 @@ include Makefile_Eolian_Cxx.am
include Makefile_Eet_Cxx.am
include Makefile_Eo_Cxx.am
include Makefile_Elua.am
.PHONY: benchmark examples
BENCHMARK_SUBDIRS = \
@ -105,7 +107,8 @@ examples/eldbus \
examples/ephysics \
examples/edje \
examples/emotion \
examples/ethumb_client
examples/ethumb_client \
examples/elua
if HAVE_CXX11
EXAMPLES_SUBDIRS += \

22
src/Makefile_Elua.am Normal file
View File

@ -0,0 +1,22 @@
if HAVE_ELUA
bin_PROGRAMS += bin/elua/elua
bin_elua_elua_SOURCES = \
bin/elua/cache.c \
bin/elua/main.c
bin_elua_elua_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
-DELUA_DATA_DIR="\"$(datadir)/elua\"" @ELUA_CFLAGS@
bin_elua_elua_LDADD = @ELUA_LIBS@
bin_elua_elua_DEPENDENCIES = @ELUA_INTERNAL_LIBS@
eluamodulesdir = $(datadir)/elua/modules
eluamodules_DATA = bin/elua/elm.lua
EXTRA_DIST += $(eluamodules_DATA)
eluacoredir = $(datadir)/elua/core
eluacore_DATA = bin/elua/module.lua
EXTRA_DIST += $(eluacore_DATA)
endif

192
src/bin/elua/cache.c Normal file
View File

@ -0,0 +1,192 @@
/* elua bytecode caching */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include "main.h"
/* bytecode caching */
static int check_bc(const char *fname, const char *mode, Eina_Bool *bc) {
const char *ext = strstr(fname, ".lua");
if (ext && !ext[4] && (!mode || strchr(mode, 't'))) {
/* loading lua source file, try cached */
char buf[PATH_MAX];
snprintf(buf, sizeof(buf), "%sc", fname);
int fd = open(buf, O_RDONLY);
if (fd < 0) {
/* no cached bytecode */
*bc = EINA_TRUE;
} else {
/* cached bytecode, check timestamp */
struct stat s1, s2;
stat(fname, &s1);
stat(buf, &s2);
if (s2.st_ctime > s1.st_ctime) {
/* bytecode new enough, chunkname stays the same */
return fd;
} else {
/* bytecode too old, remove old file */
close(fd);
*bc = EINA_TRUE;
}
}
}
return -1;
}
static int writef(lua_State *L EINA_UNUSED, const void *p, size_t size,
void *ud) {
FILE *f = ud;
return ferror(f) || (fwrite(p, 1, size, f) != size);
}
static void write_bc(lua_State *L, const char *fname) {
char buf[PATH_MAX];
snprintf(buf, sizeof(buf), "%sc", fname);
FILE *f = fopen(buf, "wb");
if (f) {
if (lua_dump(L, writef, f)) {
fclose(f);
remove(buf);
} else fclose(f);
}
}
/* loadfile - regular version */
typedef struct Cached_Stream {
FILE *f;
char buff[LUAL_BUFFERSIZE];
} Cached_Stream;
static const char *getf(lua_State *L EINA_UNUSED, void *ud, size_t *size) {
Cached_Stream *s = ud;
if (feof(s->f)) return NULL;
*size = fread(s->buff, 1, sizeof(s->buff), s->f);
return (*size > 0) ? s->buff : NULL;
}
int elua_loadfilex(lua_State *L, const char *fname, const char *mode) {
Cached_Stream s;
int status;
const char *chname;
Eina_Bool bcache = EINA_FALSE;
if (!fname) {
s.f = stdin;
chname = "=stdin";
} else {
if (!(s.f = fopen(fname, "rb"))) {
lua_pushfstring(L, "cannot open %s: %s", fname, strerror(errno));
return LUA_ERRFILE;
}
chname = lua_pushfstring(L, "@%s", fname);
int fd = check_bc(fname, mode, &bcache);
if (fd >= 0) {
fclose(s.f);
s.f = fdopen(fd, "rb");
}
}
status = lua_loadx(L, getf, &s, chname, mode);
if (ferror(s.f)) {
lua_pop(L, 1);
lua_pushfstring(L, "cannot read %s: %s", chname + 1, strerror(errno));
if (fname) {
lua_remove(L, -2);
fclose(s.f);
}
return LUA_ERRFILE;
}
/* trigger bytecode writing */
if (!status && bcache) write_bc(L, fname);
if (fname) {
lua_remove(L, -2);
fclose(s.f);
}
return status;
}
int elua_loadfile(lua_State *L, const char *fname) {
return elua_loadfilex(L, fname, NULL);
}
/* loadfile - mmap version */
typedef struct Map_Stream {
char *fmap;
size_t flen;
} Map_Stream;
static const char *getf_map(lua_State *L EINA_UNUSED, void *ud, size_t *size) {
Map_Stream *s = ud;
*size = s->flen;
return s->fmap;
}
int elua_loadfilex_mmap(lua_State *L, const char *fname, const char *mode) {
Map_Stream s;
int status, fd, nfd;
const char *chname;
Eina_Bool bcache = EINA_FALSE;
if (!fname) {
return elua_loadfilex(L, fname, mode);
}
if ((fd = open(fname, O_RDONLY, 0)) < 0) {
lua_pushfstring(L, "cannot open %s: %s", fname, strerror(errno));
return LUA_ERRFILE;
}
chname = lua_pushfstring(L, "@%s", fname);
if ((nfd = check_bc(fname, mode, &bcache)) > 0) {
close(fd);
fd = nfd;
}
s.flen = lseek(fd, 0, SEEK_END);
lseek(fd, 0, SEEK_SET);
if ((s.fmap = mmap(NULL, s.flen, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0))
== MAP_FAILED) {
lua_pushfstring(L, "cannot read %s: %s", chname + 1, strerror(errno));
lua_remove(L, -2);
return LUA_ERRFILE;
}
status = lua_loadx(L, getf_map, &s, chname, mode);
munmap(s.fmap, s.flen);
close(fd);
if (!status && bcache) write_bc(L, fname);
lua_remove(L, -2);
return status;
}
int elua_loadfile_mmap(lua_State *L, const char *fname) {
return elua_loadfilex_mmap(L, fname, NULL);
}
/* lua function */
static int loadfile(lua_State *L) {
const char *fname = luaL_optstring(L, 1, NULL);
const char *mode = luaL_optstring(L, 2, NULL);
int status, hasenv = (lua_gettop(L) >= 3);
if (lua_toboolean(L, 4)) {
status = elua_loadfilex_mmap(L, fname, mode);
} else {
status = elua_loadfilex(L, fname, mode);
}
if (!status) {
if (hasenv) {
lua_pushvalue(L, 3);
lua_setfenv(L, -2);
}
return 1;
}
lua_pushnil(L);
lua_insert(L, -2);
return 2;
}
void elua_register_cache(lua_State *L) {
lua_pushcfunction(L, loadfile);
lua_setglobal(L, "loadfile");
}

129
src/bin/elua/elm.lua Normal file
View File

@ -0,0 +1,129 @@
local ffi = require("ffi")
local util = erequire("util")
local elm, evas
local M = {}
ffi.cdef [[
typedef struct Evas_Object Evas_Object;
typedef void(*Evas_Smart_Cb)(void *data, Evas_Object *obj, void *event_info);
int elm_init(int argc, char **argv);
int elm_exit(void);
Evas_Object *elm_win_add(Evas_Object *parent, const char *name, int type);
void elm_win_title_set(Evas_Object *obj, const char *title);
void elm_win_resize_object_add(Evas_Object *obj, Evas_Object *subobj);
Evas_Object *elm_bg_add(Evas_Object *parent);
Evas_Object *elm_label_add(Evas_Object *parent);
Evas_Object *elm_button_add(Evas_Object *parent);
Evas_Object *elm_box_add(Evas_Object *parent);
void elm_box_pack_end(Evas_Object *obj, Evas_Object *subobj);
void elm_object_part_text_set(Evas_Object *obj, const char *part, const char *text);
void evas_object_show(Evas_Object *obj);
void evas_object_size_hint_weight_set(Evas_Object *obj, double x, double y);
void evas_object_resize(Evas_Object *obj, int w, int h);
void evas_object_smart_callback_add(Evas_Object *obj, const char *event, Evas_Smart_Cb func, const void *data);
void evas_object_smart_callback_del_full(Evas_Object *obj, const char *event, Evas_Smart_Cb func, const void *data);
]]
local callbacks = {}
local smart_cb_wrapper = ffi.cast("Evas_Smart_Cb",
util.register_callbacks(callbacks))
util.init_module(function()
elm, evas = ffi.load("elementary"), ffi.load("evas")
elm.elm_init(0, nil)
end, function()
elm.elm_exit()
end)
local Evas_Object = {
resize = function(self, w, h)
evas.evas_object_resize(self.__o, w, h)
end,
show = function(self) evas.evas_object_show(self.__o) end,
size_hint_weight_set = function(self, x, y)
evas.evas_object_size_hint_weight_set(self.__o, x, y)
end,
smart_callback_add = function(self, ev, cb)
local cbt = callbacks[cb]
if not cbt then
callbacks[#callbacks + 1] = cb
cbt = { #callbacks, 0 }
callbacks[cb] = cbt
end
cbt[2] = cbt[2] + 1
evas.evas_object_smart_callback_add(self.__o, ev, smart_cb_wrapper,
ffi.cast("void*", cbt[1]))
end,
smart_callback_del = function(self, ev, cb)
local cbt = callbacks[cb]
if not cbt then return end
local cbi = cbt[1]
evas.evas_object_smart_callback_del_full(self.__o, ev, smart_cb_wrapper,
ffi.cast("void*", cbi))
local cnt = cbt[2] - 1
if cnt == 0 then
callbacks[cbi], callbacks[cb] = nil, nil
else
cbt[2] = cnt
end
end
}
M.Window = function(name, title)
local o = setmetatable({
__o = elm.elm_win_add(nil, name, 0),
resize_object_add = function(self, o)
elm.elm_win_resize_object_add(self.__o, o.__o)
end
}, { __index = Evas_Object })
elm.elm_win_title_set(o.__o, title)
return o
end
M.Background = function(parent)
return setmetatable({
__o = elm.elm_bg_add(parent.__o)
}, { __index = Evas_Object })
end
M.Label = function(parent)
return setmetatable({
__o = elm.elm_label_add(parent.__o),
text_set = function(self, label)
elm.elm_object_part_text_set(self.__o, nil, label)
end
}, { __index = Evas_Object })
end
M.Button = function(parent)
return setmetatable({
__o = elm.elm_button_add(parent.__o),
text_set = function(self, label)
elm.elm_object_part_text_set(self.__o, nil, label)
end
}, { __index = Evas_Object })
end
M.Box = function(parent)
return setmetatable({
__o = elm.elm_box_add(parent.__o),
pack_end = function(self, obj)
elm.elm_box_pack_end(self.__o, obj.__o)
end
}, { __index = Evas_Object })
end
M.exit = function()
elm.elm_exit()
end
_G["elm"] = M

328
src/bin/elua/main.c Normal file
View File

@ -0,0 +1,328 @@
/* The Lua runtime component of the EFL */
#include "main.h"
static Eina_List *modlist = NULL;
static int require_ref = LUA_REFNIL;
int el_log_domain = -1;
enum {
ARG_CODE = 0, ARG_MODULE, ARG_LIBRARY
};
typedef struct Arg_Data {
int type;
const char *value;
} Arg_Data;
static Eina_Bool append_cb(const Ecore_Getopt *parser EINA_UNUSED,
const Ecore_Getopt_Desc *desc EINA_UNUSED,
const char *str,
void *data,
Ecore_Getopt_Value *val)
{
Eina_List **l = val->listp;
Arg_Data *v = malloc(sizeof(Arg_Data));
v->type = (size_t)data;
v->value = str;
*l = eina_list_append(*l, v);
return EINA_TRUE;
}
static Ecore_Getopt opt = {
"elua", "%prog [options] [script [args]]", "0.0.1", "See COPYING",
"See COPYING", "A main entry for all EFL/LuaJIT powered applications.",
0, {
ECORE_GETOPT_LICENSE('L', "license"),
ECORE_GETOPT_COPYRIGHT('c', "copyright"),
ECORE_GETOPT_VERSION('v', "version"),
ECORE_GETOPT_HELP('h', "help"),
ECORE_GETOPT_CALLBACK_ARGS('e', "execute", "Execute string "
"'code'.", "CODE", append_cb, (void*)ARG_CODE),
ECORE_GETOPT_CALLBACK_ARGS('m', "module", "Include module 'module'.",
"MODULE", append_cb, (void*)ARG_MODULE),
ECORE_GETOPT_CALLBACK_ARGS('l', "library", "Require library 'library'.",
"LIBRARY", append_cb, (void*)ARG_LIBRARY),
ECORE_GETOPT_STORE_TRUE('E', "noenv", "Ignore environment vars."),
ECORE_GETOPT_SENTINEL
}
};
static void errmsg(const char *pname, const char *msg) {
ERR("%s%s%s", pname ? pname : "", pname ? ": " : "", msg);
}
static int report(lua_State *L, int status) {
if (status && !lua_isnil(L, -1)) {
const char *msg = lua_tostring(L, -1);
errmsg(opt.prog, msg ? msg : "(non-string error)");
lua_pop(L, 1);
}
return status;
}
static int traceback(lua_State *L) {
lua_getglobal(L, "debug");
if (!lua_istable(L, -1)) {
lua_pop(L, 1);
return 1;
}
lua_getfield(L, -1, "traceback");
if (!lua_isfunction(L, -1)) {
lua_pop(L, 2);
return 1;
}
lua_pushvalue(L, 1);
lua_pushinteger(L, 2);
lua_call(L, 2, 1);
return 1;
}
static int docall(lua_State *L, int narg) {
int status;
int bs = lua_gettop(L) - narg;
lua_pushcfunction(L, traceback);
lua_insert(L, bs);
status = lua_pcall(L, narg, 0, bs);
lua_remove(L, bs);
if (status) lua_gc(L, LUA_GCCOLLECT, 0);
return status;
}
static int getargs(lua_State *L, int argc, char **argv, int n) {
int i;
int narg = argc - (n + 1);
luaL_checkstack(L, narg + 3, "too many arguments to script");
for (i = n + 1; i < argc; ++i) lua_pushstring(L, argv[i]);
lua_createtable(L, narg, n + 1);
for (i = 0; i < argc; ++i) {
lua_pushstring(L, argv[i]);
lua_rawseti(L, -2, i - n);
}
return narg;
}
static int init_module(lua_State *L) {
if (!lua_isnoneornil(L, 1)) {
lua_pushvalue(L, 1);
lua_call(L, 0, 0);
}
if (!lua_isnoneornil(L, 2)) {
lua_pushvalue(L, 2);
modlist = eina_list_append(modlist,
(void*)(size_t)luaL_ref(L, LUA_REGISTRYINDEX));
}
return 0;
}
static int register_require(lua_State *L) {
lua_pushvalue(L, 1);
require_ref = luaL_ref(L, LUA_REGISTRYINDEX);
lua_pushliteral(L, ELUA_DATA_DIR "/core/?.lua;");
lua_pushliteral(L, ELUA_DATA_DIR "/modules/?.lua;");
lua_pushvalue(L, 2);
lua_concat(L, 3);
return 1;
}
static int dolib(lua_State *L, const char *libname) {
lua_rawgeti(L, LUA_REGISTRYINDEX, require_ref);
lua_pushstring(L, libname);
return report(L, lua_pcall(L, 1, 0, 0));
}
static int dofile(lua_State *L, const char *fname) {
return report(L, elua_loadfile(L, fname) || docall(L, 0));
}
static int dostr(lua_State *L, const char *chunk, const char *chname) {
return report(L, luaL_loadbuffer(L, chunk, strlen(chunk), chname)
|| docall(L, 0));
}
static int doscript(lua_State *L, int argc, char **argv, int n) {
int status;
const char *fname = argv[n];
int narg = getargs(L, argc, argv, n);
lua_setglobal(L, "arg");
if (fname[0] == '-' && !fname[1]) {
fname = NULL;
}
status = elua_loadfile(L, fname);
lua_insert(L, -(narg + 1));
if (!status) {
status = docall(L, narg);
} else {
lua_pop(L, narg);
}
return report(L, status);
}
void shutdown(lua_State *L, int c) {
void *data;
INF("elua shutdown");
EINA_LIST_FREE(modlist, data) {
lua_rawgeti(L, LUA_REGISTRYINDEX, (size_t)data);
lua_call(L, 0, 0);
}
if (L) lua_close(L);
eina_shutdown();
exit(c);
}
static int cb_ref = LUA_REFNIL;
static lua_State *LL = NULL;
static void smart_cb_wrapper(void *data, void *obj EINA_UNUSED,
void *einfo EINA_UNUSED) {
int idx = (size_t)data;
lua_rawgeti(LL, LUA_REGISTRYINDEX, cb_ref);
lua_rawgeti(LL, -1, idx);
lua_call(LL, 0, 0);
lua_pop(LL, 1);
}
static int register_callbacks(lua_State *L) {
union { void (*fptr)(void*, void*, void*); void *ptr; } u;
lua_pushvalue(L, 1);
cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
u.fptr = smart_cb_wrapper;
lua_pushlightuserdata(L, u.ptr);
return 1;
}
struct Main_Data {
int argc;
char **argv;
int status;
};
const luaL_reg utillib[] = {
{ "init_module", init_module },
{ "register_callbacks", register_callbacks },
{ NULL, NULL }
};
/* protected main */
static int lua_main(lua_State *L) {
Eina_Bool quit = EINA_FALSE,
noenv = EINA_FALSE,
hasexec = EINA_FALSE;
Eina_List *largs = NULL, *l = NULL;
Arg_Data *data = NULL;
int nonopt;
struct Main_Data *m = (struct Main_Data*)lua_touserdata(L, 1);
int argc = m->argc;
char **argv = m->argv;
if (argv[0] && argv[0][0]) opt.prog = argv[0];
lua_gc(L, LUA_GCSTOP, 0);
luaL_openlibs(L);
elua_loadfile(L, ELUA_DATA_DIR "/core/module.lua");
lua_pushcfunction(L, register_require);
lua_createtable(L, 0, 0);
luaL_register(L, NULL, utillib);
lua_call(L, 2, 0);
elua_register_cache(L);
lua_gc(L, LUA_GCRESTART, 0);
INF("elua lua state initialized");
nonopt = ecore_getopt_parse(&opt, (Ecore_Getopt_Value[]){
ECORE_GETOPT_VALUE_BOOL(quit), /* license */
ECORE_GETOPT_VALUE_BOOL(quit), /* copyright */
ECORE_GETOPT_VALUE_BOOL(quit), /* version */
ECORE_GETOPT_VALUE_BOOL(quit), /* help */
ECORE_GETOPT_VALUE_LIST(largs),
ECORE_GETOPT_VALUE_LIST(largs),
ECORE_GETOPT_VALUE_LIST(largs),
ECORE_GETOPT_VALUE_BOOL(noenv)
}, argc, argv);
INF("arguments parsed");
if (quit) return 0;
/* load all the things */
EINA_LIST_FOREACH(largs, l, data) {
switch (data->type) {
case ARG_CODE:
if (!hasexec) hasexec = EINA_TRUE;
if (dostr(L, data->value, "=(command line)")) {
m->status = 1;
return 0;
}
break;
case ARG_MODULE:
break;
case ARG_LIBRARY:
if (dolib(L, data->value)) {
m->status = 1;
return 0;
}
break;
default:
break;
}
}
/* cleanup */
EINA_LIST_FREE(largs, data) free(data);
/* run script or execute sdin as file */
if (nonopt >= 0 && nonopt < argc) {
if ((m->status = doscript(L, argc, argv, nonopt))) return 0;
} else if (!hasexec) {
dofile(L, NULL);
}
ecore_main_loop_begin();
return 0;
}
int main(int argc, char **argv) {
struct Main_Data m;
lua_State *L = NULL;
eina_init();
if (!(el_log_domain = eina_log_domain_register("elua",
EINA_COLOR_ORANGE))) {
printf("cannot set elua log domain\n");
ERR("could not set elua log domain.");
el_log_domain = EINA_LOG_DOMAIN_GLOBAL;
}
INF("elua logging initialized: %d", el_log_domain);
if (!(L = luaL_newstate())) {
ERR("could not initialize elua state.");
shutdown(L, 1);
}
LL = L;
INF("elua lua state created");
m.argc = argc;
m.argv = argv;
m.status = 0;
shutdown(L, !!(lua_cpcall(L, lua_main, &m) || m.status));
return 0; /* never gets here */
}

37
src/bin/elua/main.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef LUAR_MAIN_H
#define LUAR_MAIN_H
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifndef ELUA_DATA_DIR
#define ELUA_DATA_DIR "."
#endif
#include <stdio.h>
#include <stdlib.h>
#include <Eina.h>
#include <Ecore.h>
#include <Ecore_Getopt.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
extern int el_log_domain;
#define DBG(...) EINA_LOG_DOM_DBG(el_log_domain, __VA_ARGS__)
#define INF(...) EINA_LOG_DOM_INFO(el_log_domain, __VA_ARGS__)
#define WRN(...) EINA_LOG_DOM_WARN(el_log_domain, __VA_ARGS__)
#define ERR(...) EINA_LOG_DOM_ERR(el_log_domain, __VA_ARGS__)
#define CRT(...) EINA_LOG_DOM_CRITICAL(el_log_domain, __VA_ARGS__)
int elua_loadfilex(lua_State *L, const char *fname, const char *mode);
int elua_loadfile(lua_State *L, const char *fname);
int elua_loadfilex_mmap(lua_State *L, const char *fname, const char *mode);
int elua_loadfile_mmap(lua_State *L, const char *fname);
void elua_register_cache(lua_State *L);
#endif

72
src/bin/elua/module.lua Normal file
View File

@ -0,0 +1,72 @@
-- elua module system
local M = {}
local util = select(2, ...)
local preload = {
util = function() return util end
}
local loaded = {
}
local path = "./?.lua;/?/init.lua"
local loaders = {
function(modname)
local v = preload[modname]
if not v then
return ("\no field preload['%s']"):format(modname)
end
return v
end,
function(modname)
local fname, err = package.searchpath(modname, path)
if not fname then return err end
local f, err = loadfile(fname)
if not f then
error("error loading module '" .. modname .. "' from file '"
.. fname .. "':\n" .. err, 2)
end
return f
end
}
M.loaders = loaders
local find_loader = function(modname, env)
env = env or _G
local err = { ("module '%s' not found\n"):format(modname) }
for i = 1, #loaders do
local v = loaders[i](modname)
if type(v) == "function" then
return setfenv(v, env)
elseif type(v) == "string" then
err[#err + 1] = v
end
end
return nil, table.concat(err)
end
M.require = function(modname)
local v = loaded[modname]
if v ~= nil then return v end
local loader, err = find_loader(modname)
if not loader then error(err, 2) end
local ret = loader(modname)
if ret ~= nil then
loaded[modname] = ret
return ret
elseif loaded[modname] == nil then
loaded[modname] = true
return true
end
return loaded[modname]
end
-- register require
path = (...)(M.require, path)
_G["erequire"] = M.require
return M

View File

@ -0,0 +1,17 @@
if HAVE_ELUA
MAINTAINERCLEANFILES = Makefile.in
DATA_FILES = Makefile.examples
EXTRA_DIST = $(DATA_FILES)
install-examples:
mkdir -p $(datadir)/elua/examples
$(install_sh_DATA) -c $(DATA_FILES) $(datadir)/elua/examples
uninstall-local:
for f in $(DATA_FILES); do \
rm -f $(datadir)/elua/examples/$$f ; \
done
endif

View File

@ -0,0 +1,38 @@
local win = elm.Window("test", "Hello World")
win:smart_callback_add("delete,request", function()
elm.exit()
end)
local bg = elm.Background(win)
bg:size_hint_weight_set(1.0, 1.0)
win:resize_object_add(bg)
bg:show()
local bx = elm.Box(win)
bx:size_hint_weight_set(1.0, 1.0)
win:resize_object_add(bx)
bx:show()
local lbl = elm.Label(win)
lbl:text_set("Lua runtime test")
bx:pack_end(lbl)
lbl:show()
local counter = nil
local step = 5
local btn = elm.Button(win)
btn:text_set("Reset counter")
bx:pack_end(btn)
btn:smart_callback_add("clicked", function()
if not counter then
btn:text_set("Add " .. step)
end
counter = counter and (counter + step) or 0
lbl:text_set(tostring(counter))
end)
btn:show()
win:resize(360, 360)
win:show()