1
1
mirror of https://github.com/profanity-im/profanity.git synced 2025-02-02 15:08:15 -05:00

Added basic empty lua api and hooks

This commit is contained in:
James Booth 2013-09-15 13:51:23 +01:00
parent 6788197a6b
commit 5da3026546
8 changed files with 737 additions and 4 deletions

View File

@ -39,6 +39,10 @@ ruby_sources = \
src/plugins/ruby_plugins.h src/plugins/ruby_plugins.c \
src/plugins/ruby_api.h src/plugins/ruby_api.c
lua_sources = \
src/plugins/lua_plugins.h src/plugins/lua_plugins.c \
src/plugins/lua_api.h src/plugins/lua_api.c
test_sources = \
tests/test_roster.c tests/test_common.c tests/test_history.c \
tests/test_autocomplete.c tests/testsuite.c tests/test_parser.c \
@ -56,8 +60,14 @@ else
with_ruby_sources = $(with_python_sources)
endif
if BUILD_LUA_API
with_lua_sources = $(with_ruby_sources) $(lua_sources)
else
with_lua_sources = $(with_ruby_sources)
endif
bin_PROGRAMS = profanity
profanity_SOURCES = $(main_source) $(with_ruby_sources)
profanity_SOURCES = $(main_source) $(with_lua_sources)
lib_LTLIBRARIES = libprofanity.la
libprofanity_la_LDFLAGS=-module -avoid-version -shared
@ -68,7 +78,7 @@ library_include_HEADERS = src/plugins/profapi.h
TESTS = tests/testsuite
check_PROGRAMS = tests/testsuite
tests_testsuite_SOURCES = $(with_ruby_sources) $(test_sources)
tests_testsuite_SOURCES = $(with_lua_sources) $(test_sources)
tests_testsuite_LDADD = -lheadunit -lstdc++
man_MANS = docs/profanity.1

View File

@ -41,6 +41,14 @@ else
AC_MSG_NOTICE([Python development package not found, Python plugin support disabled.])
fi
AX_PROG_LUA
AX_LUA_HEADERS
AX_LUA_LIBS
LUA_INCLUDE="-I/usr/include/lua5.1"
LUA_LIB="-llua5.1"
AM_CONDITIONAL([BUILD_LUA_API], [true])
AC_DEFINE([HAVE_LUA], [1], [Lua support])
# Checks for programs.
AC_PROG_CC
@ -129,8 +137,8 @@ if test "x$PACKAGE_STATUS" = xdevelopment; then
fi
LIBS="$LIBS $DEPS_LIBS $NOTIFY_LIBS"
AM_LDFLAGS="$AM_LDFLAGS $PYTHON_LDFLAGS $RUBY_LDFLAGS"
AM_CPPFLAGS="$DEPS_CFLAGS $NOTIFY_CFLAGS $PYTHON_CPPFLAGS $RUBY_CPPFLAGS"
AM_LDFLAGS="$AM_LDFLAGS $PYTHON_LDFLAGS $RUBY_LDFLAGS $LUA_LIB"
AM_CPPFLAGS="$DEPS_CFLAGS $NOTIFY_CFLAGS $PYTHON_CPPFLAGS $RUBY_CPPFLAGS $LUA_INCLUDE"
AC_SUBST(AM_LDFLAGS)
AC_SUBST(AM_CFLAGS)

386
src/plugins/lua_api.c Normal file
View File

@ -0,0 +1,386 @@
/*
* lua_api.c
*
* Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
* Profanity is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Profanity is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <lua.h>
#include <glib.h>
#include "plugins/api.h"
#include "plugins/lua_api.h"
#include "plugins/callbacks.h"
static int
lua_api_cons_alert(lua_State *L)
{
api_cons_alert();
return 0;
}
static int
lua_api_cons_show(lua_State *L)
{
const char *message = lua_tostring(L, 1);
api_cons_show(message);
return 0;
}
static int
lua_api_register_command(lua_State *L)
{
/*
const char *command_name = NULL;
int min_args = 0;
int max_args = 0;
const char *usage = NULL;
const char *short_help = NULL;
const char *long_help = NULL;
PyObject *p_callback = NULL;
if (!PyArg_ParseTuple(args, "siisssO", &command_name, &min_args, &max_args,
&usage, &short_help, &long_help, &p_callback)) {
return Py_BuildValue("");
}
if (p_callback && PyCallable_Check(p_callback)) {
api_register_command(command_name, min_args, max_args, usage,
short_help, long_help, p_callback, python_command_callback);
}
return Py_BuildValue("");
*/
return 0;
}
static int
lua_api_register_timed(lua_State *L)
{
/*
PyObject *p_callback = NULL;
int interval_seconds = 0;
if (!PyArg_ParseTuple(args, "Oi", &p_callback, &interval_seconds)) {
return Py_BuildValue("");
}
if (p_callback && PyCallable_Check(p_callback)) {
api_register_timed(p_callback, interval_seconds, python_timed_callback);
}
return Py_BuildValue("");
*/
return 0;
}
static int
lua_api_notify(lua_State *L)
{
/*
const char *message = NULL;
const char *category = NULL;
int timeout_ms = 5000;
if (!PyArg_ParseTuple(args, "sis", &message, &timeout_ms, &category)) {
return Py_BuildValue("");
}
api_notify(message, category, timeout_ms);
return Py_BuildValue("");
*/
return 0;
}
static int
lua_api_send_line(lua_State *L)
{
/*
char *line = NULL;
if (!PyArg_ParseTuple(args, "s", &line)) {
return Py_BuildValue("");
}
api_send_line(line);
return Py_BuildValue("");
*/
return 0;
}
static int
lua_api_get_current_recipient(lua_State *L)
{
/*
char *recipient = api_get_current_recipient();
if (recipient != NULL) {
return Py_BuildValue("s", recipient);
} else {
return Py_BuildValue("");
}
*/
return 0;
}
static int
lua_api_log_debug(lua_State *L)
{
/*
const char *message = NULL;
if (!PyArg_ParseTuple(args, "s", &message)) {
return Py_BuildValue("");
}
api_log_debug(message);
return Py_BuildValue("");
*/
return 0;
}
static int
lua_api_log_info(lua_State *L)
{
/*
const char *message = NULL;
if (!PyArg_ParseTuple(args, "s", &message)) {
return Py_BuildValue("");
}
api_log_info(message);
return Py_BuildValue("");
*/
}
static int
lua_api_log_warning(lua_State *L)
{
/*
const char *message = NULL;
if (!PyArg_ParseTuple(args, "s", &message)) {
return Py_BuildValue("");
}
api_log_warning(message);
return Py_BuildValue("");
*/
return 0;
}
static int
lua_api_log_error(lua_State *L)
{
/*
const char *message = NULL;
if (!PyArg_ParseTuple(args, "s", &message)) {
return Py_BuildValue("");
}
api_log_error(message);
return Py_BuildValue("");
*/
return 0;
}
static int
lua_api_win_exists(lua_State *L)
{
/*
char *tag = NULL;
if (!PyArg_ParseTuple(args, "s", &tag)) {
return Py_BuildValue("");
}
if (api_win_exists(tag)) {
return Py_BuildValue("i", 1);
} else {
return Py_BuildValue("i", 0);
}
*/
return 0;
}
static int
lua_api_win_create(lua_State *L)
{
/*
char *tag = NULL;
PyObject *p_callback = NULL;
if (!PyArg_ParseTuple(args, "sO", &tag, &p_callback)) {
return Py_BuildValue("");
}
if (p_callback && PyCallable_Check(p_callback)) {
api_win_create(tag, p_callback, python_window_callback);
}
return Py_BuildValue("");
*/
return 0;
}
static int
lua_api_win_focus(lua_State *L)
{
/*
char *tag = NULL;
if (!PyArg_ParseTuple(args, "s", &tag)) {
return Py_BuildValue("");
}
api_win_focus(tag);
return Py_BuildValue("");
*/
return 0;
}
static int
lua_api_win_process_line(lua_State *L)
{
/*
char *tag = NULL;
char *line = NULL;
if (!PyArg_ParseTuple(args, "ss", &tag, &line)) {
return Py_BuildValue("");
}
api_win_process_line(tag, line);
return Py_BuildValue("");
*/
return 0;
}
static int
lua_api_win_show(lua_State *L)
{
/*
char *tag = NULL;
char *line = NULL;
if (!PyArg_ParseTuple(args, "ss", &tag, &line)) {
return Py_BuildValue("");
}
api_win_show(tag, line);
return Py_BuildValue("");
*/
return 0;
}
void
lua_command_callback(PluginCommand *command, gchar **args)
{
/*
PyObject *p_args = NULL;
int num_args = g_strv_length(args);
if (num_args == 0) {
if (command->max_args == 1) {
p_args = Py_BuildValue("(O)", Py_BuildValue(""));
PyObject_CallObject(command->callback, p_args);
Py_XDECREF(p_args);
} else {
PyObject_CallObject(command->callback, p_args);
}
} else if (num_args == 1) {
p_args = Py_BuildValue("(s)", args[0]);
PyObject_CallObject(command->callback, p_args);
Py_XDECREF(p_args);
} else if (num_args == 2) {
p_args = Py_BuildValue("ss", args[0], args[1]);
PyObject_CallObject(command->callback, p_args);
Py_XDECREF(p_args);
} else if (num_args == 3) {
p_args = Py_BuildValue("sss", args[0], args[1], args[2]);
PyObject_CallObject(command->callback, p_args);
Py_XDECREF(p_args);
} else if (num_args == 4) {
p_args = Py_BuildValue("ssss", args[0], args[1], args[2], args[3]);
PyObject_CallObject(command->callback, p_args);
Py_XDECREF(p_args);
} else if (num_args == 5) {
p_args = Py_BuildValue("sssss", args[0], args[1], args[2], args[3], args[4]);
PyObject_CallObject(command->callback, p_args);
Py_XDECREF(p_args);
}
if (PyErr_Occurred()) {
PyErr_Print();
PyErr_Clear();
}
*/
}
void
lua_timed_callback(PluginTimedFunction *timed_function)
{
/*
PyObject_CallObject(timed_function->callback, NULL);
*/
}
void
lua_window_callback(PluginWindowCallback *window_callback, char *tag, char *line)
{
/*
PyObject *p_args = NULL;
p_args = Py_BuildValue("ss", tag, line);
PyObject_CallObject(window_callback->callback, p_args);
Py_XDECREF(p_args);
if (PyErr_Occurred()) {
PyErr_Print();
PyErr_Clear();
}
*/
}
void
lua_api_init(lua_State *L)
{
lua_pushcfunction(L, lua_api_cons_alert);
lua_setglobal(L, "prof_cons_alert");
lua_pushcfunction(L, lua_api_cons_show);
lua_setglobal(L, "prof_cons_show");
lua_pushcfunction(L, lua_api_register_command);
lua_setglobal(L, "prof_register_command");
lua_pushcfunction(L, lua_api_register_timed);
lua_setglobal(L, "prof_register_timed");
lua_pushcfunction(L, lua_api_send_line);
lua_setglobal(L, "prof_send_line");
lua_pushcfunction(L, lua_api_notify);
lua_setglobal(L, "prof_notify");
lua_pushcfunction(L, lua_api_get_current_recipient);
lua_setglobal(L, "prof_get_current_recipient");
lua_pushcfunction(L, lua_api_log_debug);
lua_setglobal(L, "prof_log_debug");
lua_pushcfunction(L, lua_api_log_info);
lua_setglobal(L, "prof_log_info");
lua_pushcfunction(L, lua_api_log_warning);
lua_setglobal(L, "prof_log_warning");
lua_pushcfunction(L, lua_api_log_error);
lua_setglobal(L, "prof_log_error");
lua_pushcfunction(L, lua_api_win_exists);
lua_setglobal(L, "prof_win_exists");
lua_pushcfunction(L, lua_api_win_create);
lua_setglobal(L, "prof_win_create");
lua_pushcfunction(L, lua_api_win_focus);
lua_setglobal(L, "prof_win_focus");
lua_pushcfunction(L, lua_api_win_show);
lua_setglobal(L, "prof_win_show");
lua_pushcfunction(L, lua_api_win_process_line);
lua_setglobal(L, "prof_win_process_line");
}

36
src/plugins/lua_api.h Normal file
View File

@ -0,0 +1,36 @@
/*
* lua_api.h
*
* Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
* Profanity is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Profanity is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef LUA_API_H
#define LUA_API_H
#include <lua.h>
void lua_env_init(void);
void lua_api_init(lua_State *L);
void lua_shutdown(void);
void lua_command_callback(PluginCommand *command, gchar **args);
void lua_timed_callback(PluginTimedFunction *timed_function);
void lua_window_callback(PluginWindowCallback *window_callback, char *tag, char *line);
#endif

218
src/plugins/lua_plugins.c Normal file
View File

@ -0,0 +1,218 @@
/*
* lua_plugins.c
*
* Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
* Profanity is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Profanity is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <string.h>
#include <stdlib.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include "config/preferences.h"
#include "plugins/api.h"
#include "plugins/callbacks.h"
#include "plugins/plugins.h"
#include "plugins/lua_api.h"
#include "plugins/lua_plugins.h"
#include "ui/ui.h"
static lua_State *L;
void
lua_env_init(void)
{
L = luaL_newstate();
luaL_openlibs(L);
lua_api_init(L);
}
ProfPlugin *
lua_plugin_create(const char * const filename)
{
gchar *plugins_dir = plugins_get_dir();
GString *abs_path = g_string_new(plugins_dir);
g_string_append(abs_path, "/");
g_string_append(abs_path, filename);
int load_result = luaL_loadfile(L, abs_path->str);
lua_check_error(load_result);
// first call returns function
int call_result = lua_pcall(L, 0, 0, 0);
lua_check_error(call_result);
// store reference to function table
int r = luaL_ref(L, LUA_REGISTRYINDEX);
gchar *module_name = g_strndup(filename, strlen(filename) - 4);
if (load_result == 0 && call_result == 0) {
cons_debug("LOADING PLUGIN");
ProfPlugin *plugin = malloc(sizeof(ProfPlugin));
plugin->name = strdup(module_name);
plugin->lang = LANG_LUA;
plugin->module = &r;
plugin->init_func = lua_init_hook;
plugin->on_start_func = lua_on_start_hook;
plugin->on_connect_func = lua_on_connect_hook;
plugin->on_disconnect_func = lua_on_disconnect_hook;
plugin->on_message_received_func = lua_on_message_received_hook;
plugin->on_room_message_received_func = lua_on_room_message_received_hook;
plugin->on_private_message_received_func = lua_on_private_message_received_hook;
plugin->on_message_send_func = lua_on_message_send_hook;
plugin->on_private_message_send_func = lua_on_private_message_send_hook;
plugin->on_room_message_send_func = lua_on_room_message_send_hook;
plugin->on_shutdown_func = lua_on_shutdown_hook;
g_free(module_name);
g_free(plugins_dir);
g_string_free(abs_path, TRUE);
return plugin;
} else {
g_free(plugins_dir);
g_string_free(abs_path, TRUE);
g_free(module_name);
return NULL;
}
}
void
lua_init_hook(ProfPlugin *plugin, const char * const version, const char * const status)
{
/*
int *p_ref = (int *)plugin->module;
cons_debug("OK 1");
// push function table
lua_rawgeti(L, LUA_REGISTRYINDEX, *p_ref);
cons_debug("OK 2");
int res1 = lua_pcall(L, 0, 0, 0);
lua_check_error(res1);
cons_debug("OK 2.1");
// push key
lua_pushstring(L, "prof_init");
cons_debug("OK 3");
// push args
lua_pushstring(L, version);
lua_pushstring(L, status);
cons_debug("OK 4");
// push function
lua_gettable(L, -2);
cons_debug("OK 5");
int res2 = lua_pcall(L, 0, 0, 0);
lua_check_error(res2);
cons_debug("OK 6");
*/
}
void
lua_on_start_hook(ProfPlugin *plugin)
{
}
void
lua_on_connect_hook(ProfPlugin *plugin, const char * const account_name,
const char * const fulljid)
{
}
void
lua_on_disconnect_hook(ProfPlugin *plugin, const char * const account_name,
const char * const fulljid)
{
}
char *
lua_on_message_received_hook(ProfPlugin *plugin, const char * const jid,
const char *message)
{
return NULL;
}
char *
lua_on_private_message_received_hook(ProfPlugin *plugin, const char * const room,
const char * const nick, const char *message)
{
return NULL;
}
char *
lua_on_room_message_received_hook(ProfPlugin *plugin, const char * const room,
const char * const nick, const char *message)
{
return NULL;
}
char *
lua_on_message_send_hook(ProfPlugin *plugin, const char * const jid,
const char *message)
{
return NULL;
}
char *
lua_on_private_message_send_hook(ProfPlugin *plugin, const char * const room,
const char * const nick, const char *message)
{
return NULL;
}
char *
lua_on_room_message_send_hook(ProfPlugin *plugin, const char * const room,
const char *message)
{
return NULL;
}
void
lua_on_shutdown_hook(ProfPlugin *plugin)
{
}
void
lua_check_error(int value)
{
if (value) {
cons_debug("%s", lua_tostring(L, -1));
lua_pop(L, 1);
} else {
cons_debug("Success");
}
}
void
lua_plugin_destroy(ProfPlugin *plugin)
{
free(plugin->name);
free(plugin);
}
void
lua_shutdown(void)
{
lua_close(L);
}

49
src/plugins/lua_plugins.h Normal file
View File

@ -0,0 +1,49 @@
/*
* lua_plugins.h
*
* Copyright (C) 2012, 2013 James Booth <boothj5@gmail.com>
*
* This file is part of Profanity.
*
* Profanity is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Profanity is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef LUA_PLUGINS_H
#define LUA_PLUGINS_H
#include "plugins/plugins.h"
ProfPlugin* lua_plugin_create(const char * const filename);
void lua_init_hook(ProfPlugin *plugin, const char * const version, const char * const status);
void lua_on_start_hook(ProfPlugin *plugin);
void lua_on_connect_hook(ProfPlugin *plugin, const char * const account_name, const char * const fulljid);
void lua_on_disconnect_hook(ProfPlugin *plugin, const char * const account_name, const char * const fulljid);
char * lua_on_message_received_hook(ProfPlugin *plugin, const char * const jid, const char *message);
char * lua_on_private_message_received_hook(ProfPlugin *plugin, const char * const room,
const char * const nick, const char *message);
char * lua_on_room_message_received_hook(ProfPlugin *plugin, const char * const room,
const char * const nick, const char *message);
char * lua_on_message_send_hook(ProfPlugin *plugin, const char * const jid, const char *message);
char * lua_on_private_message_send_hook(ProfPlugin *plugin, const char * const room,
const char * const nick, const char *message);
char * lua_on_room_message_send_hook(ProfPlugin *plugin, const char * const room,
const char *message);
void lua_on_shutdown_hook(ProfPlugin *plugin);
void lua_plugin_destroy(ProfPlugin *plugin);
void lua_check_error(int value);
#endif

View File

@ -40,6 +40,11 @@
#include "plugins/ruby_api.h"
#endif
#ifdef PROF_HAVE_LUA
#include "plugins/lua_plugins.h"
#include "plugins/lua_api.h"
#endif
#include "plugins/c_plugins.h"
#include "plugins/c_api.h"
#include "ui/ui.h"
@ -56,6 +61,9 @@ plugins_init(void)
#endif
#ifdef PROF_HAVE_RUBY
ruby_env_init();
#endif
#ifdef PROF_HAVE_LUA
lua_env_init();
#endif
c_env_init();
@ -84,6 +92,15 @@ plugins_init(void)
loaded = TRUE;
}
}
#endif
#ifdef PROF_HAVE_LUA
if (g_str_has_suffix(filename, ".lua")) {
ProfPlugin *plugin = lua_plugin_create(filename);
if (plugin != NULL) {
plugins = g_slist_append(plugins, plugin);
loaded = TRUE;
}
}
#endif
if (g_str_has_suffix(filename, ".so")) {
ProfPlugin *plugin = c_plugin_create(filename);
@ -326,6 +343,11 @@ plugins_shutdown(void)
if (plugin->lang == LANG_RUBY) {
ruby_plugin_destroy(plugin);
}
#endif
#ifdef PROF_HAVE_LUA
if (plugin->lang == LANG_LUA) {
lua_plugin_destroy(plugin);
}
#endif
if (plugin->lang == LANG_C) {
c_plugin_destroy(plugin);
@ -338,6 +360,9 @@ plugins_shutdown(void)
#endif
#ifdef PROF_HAVE_RUBY
ruby_shutdown();
#endif
#ifdef PROF_HAVE_LUA
lua_shutdown();
#endif
c_shutdown();
}

View File

@ -26,6 +26,7 @@
typedef enum {
LANG_PYTHON,
LANG_RUBY,
LANG_LUA,
LANG_C
} lang_t;