diff --git a/configure.ac b/configure.ac index c6ededf12..5368e1cde 100644 --- a/configure.ac +++ b/configure.ac @@ -51,6 +51,41 @@ else AC_DEFINE([UNKNOWN], [], [Compiling on Unknown]) fi +# Check for Lua. +echo '----------------------------------------------------------' + +AC_ARG_ENABLE(lua, [--disable-lua Turn off building of Lua library (default=compiled if found)],enable_lua=$enableval,enable_lua=yes) +AC_ARG_WITH(lua-inc, [--with-lua-inc=DIR, Lua include files are in DIR],lua_inc=$withval,lua_inc='') +AC_ARG_WITH(lua-lib, [--with-lua-lib=DIR, Lua library files are in DIR],lua_lib=$withval,lua_lib='') + +if test "x$enable_lua" = "xyes" ; then + ac_save_CPPFLAGS="$CPPFLAGS" + ac_save_CFLAGS="$CFLAGS" + ac_save_LDFLAGS="$LDFLAGS" + + LUA_CFLAGS="" + LUA_LFLAGS="" + + if test -n "$lua_inc"; then + CFLAGS="$CFLAGS -I$lua_inc" + CPPFLAGS="$CPPFLAGS -I$lua_inc" + fi + if test -n "$lua_lib"; then + LDFLAGS="$LDFLAGS -L$lua_lib" + LUA_LFLAGS="-llua" + fi +fi + +if test "x$enable_lua" = "xyes" ; then + AC_SUBST(LUA_CFLAGS) + AC_SUBST(LUA_LFLAGS) + AC_DEFINE([HAVE_LIBLUA], [1], [Building with Lua support]) +fi + +AM_CONDITIONAL(HAVE_LIBLUA, test "$enable_lua" = "yes") + +echo '----------------------------------------------------------' + AM_INIT_AUTOMAKE AC_CONFIG_SRCDIR([src/main.cpp]) AC_CONFIG_HEADER([auto.h]) diff --git a/src/API.cpp b/src/API.cpp new file mode 100644 index 000000000..1547364ab --- /dev/null +++ b/src/API.cpp @@ -0,0 +1,450 @@ +//////////////////////////////////////////////////////////////////////////////// +// Task Lua API +// +// Copyright 2006 - 2010, Paul Beckingham. +// All rights reserved. +// +// This program 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 2 of the License, or (at your option) any later +// version. +// +// This program 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 +// this program; if not, write to the +// +// Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, +// Boston, MA +// 02110-1301 +// USA +// +//////////////////////////////////////////////////////////////////////////////// + +#include "API.h" + +#ifdef HAVE_LIBLUA + +//////////////////////////////////////////////////////////////////////////////// +// Returns a string representing the task version number, such as '1.9.0'. +static int api_task_version (lua_State* L) +{ + lua_pushstring (L, PACKAGE_VERSION); + return 1; +} + +//////////////////////////////////////////////////////////////////////////////// +// Returns a string representing the Lua version number, such as '5.1.4'. +// Lua 5.2.0 has a 'lua_version' call, but 5.1.4 is the target. +static int api_task_lua_version (lua_State* L) +{ + // Convert "Lua 5.1.4" -> "5.1.4" + std::string ver = LUA_RELEASE; + lua_pushstring (L, ver.substr (4, std::string::npos).c_str ()); + return 1; +} + +//////////////////////////////////////////////////////////////////////////////// +// Returns the type of OS that task is running on. +static int api_task_os (lua_State* L) +{ +#if defined (DARWIN) + lua_pushstring (L, "darwin"); +#elif defined (SOLARIS) + lua_pushstring (L, "solaris"); +#elif defined (CYGWIN) + lua_pushstring (L, "cygwin"); +#elif defined (OPENBSD) + lua_pushstring (L, "openbsd"); +#elif defined (HAIKU) + lua_pushstring (L, "haiku"); +#elif defined (FREEBSD) + lua_pushstring (L, "freebsd"); +#elif defined (LINUX) + lua_pushstring (L, "linux"); +#else + lua_pushstring (L, "unknown"); +#endif + + return 1; +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_feature (lua_State* L) +{ + std::string name = luaL_checkstring (L, 1); + bool value = false; + + if (name == "readline") + { +#ifdef HAVE_READLINE + value = true; +#endif + } + + else if (name == "ncurses") + { +#ifdef HAVE_NCURSES + value = true; +#endif + } + + lua_pushnumber (L, value ? 1 : 0); + return 1; +} + +/* +//////////////////////////////////////////////////////////////////////////////// +static int api_task_aliases () +{ + return {}; +} + +//////////////////////////////////////////////////////////////////////////////// +-- Returns values from .taskrc, by name. +static int api_task_get_config (name) +{ + return "foo" +} + +//////////////////////////////////////////////////////////////////////////////// +-- Temporarily sets .taskrc values, by name. +static int api_task_set_config (name, value) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +-- Returns an internationalized string, by string ID, from the appropriate +-- locale-based strings file. +static int api_task_i18n_string (id) +{ + return "le foo" +} + +//////////////////////////////////////////////////////////////////////////////// +-- Returns a list of tips, from the appropriate locale-based tips file. +static int api_task_i18n_tips () +{ + return {} +} + +//////////////////////////////////////////////////////////////////////////////// +-- Returns the name of the current command. +static int api_task_get_command () +{ + return "list" +} + +//////////////////////////////////////////////////////////////////////////////// +-- Returns a list of string messages generated so far. +static int api_task_get_header_messages () +{ + return {} +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_footnote_messages () +{ + return {} +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_debug_messages () +{ + return {} +} + +//////////////////////////////////////////////////////////////////////////////// +-- Records additional messages, for subsequent display. +static int api_task_header_message (text) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_footnote_message (text) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_debug_message (text) +{ +} +*/ + +//////////////////////////////////////////////////////////////////////////////// +// Causes the shell or interactive mode task to exit. Ordinarily this does not +// occur. +static int api_task_exit (lua_State* L) +{ + // TODO Is this the correct exception? How does the shell handle this? + throw std::string ("Exiting."); + return 0; +} + +/* +//////////////////////////////////////////////////////////////////////////////// +-- Shuts off the hook system for any subsequent hook calls for this command. +static int api_task_inhibit_further_hooks () +{ +} + +//////////////////////////////////////////////////////////////////////////////// +-- Returns a table that contains a complete copy of the task. +static int api_task_get (id) +{ + return task +} + +//////////////////////////////////////////////////////////////////////////////// +-- Creates a new task from the data specified in the table t. +static int api_task_add (t) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +-- Modifies the task described in the table t. +static int api_task_modify (t) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +-- 'id' is the task id passed to the hook function. Date attributes are +-- returned as a numeric epoch offset. Tags and annotations are returned +-- as tables. A nil value indicates a missing value. +static int api_task_get_uuid (id) +{ + return task.uuid +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_description (id) +{ + return task.description +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_annotations (id) +{ + return task.annotations +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_project (id) +{ + return task.project +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_priority (id) +{ + return task.priority +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_tags (id) +{ + return task.tags +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_status (id) +{ + return task.status +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_due (id) +{ + return task.due_date +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_entry (id) +{ + return task.entry_date +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_start (id) +{ + return task.start_date +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_end (id) +{ + return task.end_date +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_recur (id) +{ + return task.recur +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_until (id) +{ + return task.until_date +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_get_wait (id) +{ + return task.wait_date +} + +//////////////////////////////////////////////////////////////////////////////// +-- 'id' is the task id passed to the hook function. Date attributes are +-- expected as numeric epoch offsets. Tags and annotations are expected +-- as tables. A nil value indicates a missing value. +static int api_task_set_description (id, value) +{ + task.description = value +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_set_annotations (id, value) +{ + task.annotations = value +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_set_project (id, value) +{ + task.project = value +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_set_priority (id, value) +{ + task.priority = value +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_set_tags (id, value) +{ + task.tags = value +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_set_status (id, value) +{ + task.status = value +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_set_due (id, value) +{ + task.due_date = value +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_set_start (id, value) +{ + task.start_date = value +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_set_recur (id, value) +{ + task.recur = value +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_set_until (id, value) +{ + task.until_date = value +} + +//////////////////////////////////////////////////////////////////////////////// +static int api_task_set_wait (id, value) +{ + task.wait_date = value +} +*/ + +//////////////////////////////////////////////////////////////////////////////// +API::API () +: L (NULL) +{ +} + +//////////////////////////////////////////////////////////////////////////////// +API::~API () +{ + if (L) + { + lua_close (L); + L = NULL; + } +} + +//////////////////////////////////////////////////////////////////////////////// +void API::initialize () +{ + // Initialize Lua. + L = lua_open (); + luaL_openlibs (L); + + // Register all the API functions in Lua global space. + lua_pushcfunction (L, api_task_version); lua_setglobal (L, "task_version"); + lua_pushcfunction (L, api_task_lua_version); lua_setglobal (L, "task_lua_version"); + lua_pushcfunction (L, api_task_os); lua_setglobal (L, "task_os"); + lua_pushcfunction (L, api_task_feature); lua_setglobal (L, "task_feature"); +/* + lua_pushcfunction (L, api_task_aliases); lua_setglobal (L, "api_task_aliases"); + lua_pushcfunction (L, api_task_get_config); lua_setglobal (L, "api_task_get_config"); + lua_pushcfunction (L, api_task_set_config); lua_setglobal (L, "api_task_set_config"); + lua_pushcfunction (L, api_task_i18n_string); lua_setglobal (L, "api_task_i18n_string"); + lua_pushcfunction (L, api_task_i18n_tips); lua_setglobal (L, "api_task_i18n_tips"); + lua_pushcfunction (L, api_task_get_command); lua_setglobal (L, "api_task_get_command"); + lua_pushcfunction (L, api_task_get_header_messages); lua_setglobal (L, "api_task_get_header_messages"); + lua_pushcfunction (L, api_task_get_footnote_messages); lua_setglobal (L, "api_task_get_footnote_messages"); + lua_pushcfunction (L, api_task_get_debug_messages); lua_setglobal (L, "api_task_get_debug_messages"); + lua_pushcfunction (L, api_task_header_message); lua_setglobal (L, "api_task_header_message"); + lua_pushcfunction (L, api_task_footnote_message); lua_setglobal (L, "api_task_footnote_message"); + lua_pushcfunction (L, api_task_debug_message); lua_setglobal (L, "api_task_debug_message"); +*/ + lua_pushcfunction (L, api_task_exit); lua_setglobal (L, "task_exit"); +/* + lua_pushcfunction (L, api_task_inhibit_further_hooks); lua_setglobal (L, "api_task_inhibit_further_hooks"); + lua_pushcfunction (L, api_task_get); lua_setglobal (L, "api_task_get"); + lua_pushcfunction (L, api_task_add); lua_setglobal (L, "api_task_add"); + lua_pushcfunction (L, api_task_modify); lua_setglobal (L, "api_task_modify"); + lua_pushcfunction (L, api_task_get_uuid); lua_setglobal (L, "api_task_get_uuid"); + lua_pushcfunction (L, api_task_get_description); lua_setglobal (L, "api_task_get_description"); + lua_pushcfunction (L, api_task_get_annotations); lua_setglobal (L, "api_task_get_annotations"); + lua_pushcfunction (L, api_task_get_project); lua_setglobal (L, "api_task_get_project"); + lua_pushcfunction (L, api_task_get_priority); lua_setglobal (L, "api_task_get_priority"); + lua_pushcfunction (L, api_task_get_tags); lua_setglobal (L, "api_task_get_tags"); + lua_pushcfunction (L, api_task_get_status); lua_setglobal (L, "api_task_get_status"); + lua_pushcfunction (L, api_task_get_due); lua_setglobal (L, "api_task_get_due"); + lua_pushcfunction (L, api_task_get_entry); lua_setglobal (L, "api_task_get_entry"); + lua_pushcfunction (L, api_task_get_start); lua_setglobal (L, "api_task_get_start"); + lua_pushcfunction (L, api_task_get_end); lua_setglobal (L, "api_task_get_end"); + lua_pushcfunction (L, api_task_get_recur); lua_setglobal (L, "api_task_get_recur"); + lua_pushcfunction (L, api_task_get_until); lua_setglobal (L, "api_task_get_until"); + lua_pushcfunction (L, api_task_get_wait); lua_setglobal (L, "api_task_get_wait"); + lua_pushcfunction (L, api_task_set_description); lua_setglobal (L, "api_task_set_description"); + lua_pushcfunction (L, api_task_set_annotations); lua_setglobal (L, "api_task_set_annotations"); + lua_pushcfunction (L, api_task_set_project); lua_setglobal (L, "api_task_set_project"); + lua_pushcfunction (L, api_task_set_priority); lua_setglobal (L, "api_task_set_priority"); + lua_pushcfunction (L, api_task_set_tags); lua_setglobal (L, "api_task_set_tags"); + lua_pushcfunction (L, api_task_set_status); lua_setglobal (L, "api_task_set_status"); + lua_pushcfunction (L, api_task_set_due); lua_setglobal (L, "api_task_set_due"); + lua_pushcfunction (L, api_task_set_start); lua_setglobal (L, "api_task_set_start"); + lua_pushcfunction (L, api_task_set_recur); lua_setglobal (L, "api_task_set_recur"); + lua_pushcfunction (L, api_task_set_until); lua_setglobal (L, "api_task_set_until"); + lua_pushcfunction (L, api_task_set_wait); lua_setglobal (L, "api_task_set_wait"); +*/ +} + +//////////////////////////////////////////////////////////////////////////////// + +#endif + diff --git a/src/API.h b/src/API.h new file mode 100644 index 000000000..c6f3c9846 --- /dev/null +++ b/src/API.h @@ -0,0 +1,57 @@ +//////////////////////////////////////////////////////////////////////////////// +// task - a command line task list manager. +// +// Copyright 2006 - 2010, Paul Beckingham. +// All rights reserved. +// +// This program 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 2 of the License, or (at your option) any later +// version. +// +// This program 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 +// this program; if not, write to the +// +// Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, +// Boston, MA +// 02110-1301 +// USA +// +//////////////////////////////////////////////////////////////////////////////// +#ifndef INCLUDED_API +#define INCLUDED_API + +#include "auto.h" +#ifdef HAVE_LIBLUA + +#include +extern "C" +{ + #include "lua.h" + #include "lualib.h" + #include "lauxlib.h" +} + +class API +{ +public: + API (); + API (const API&); + API& operator= (const API&); + ~API (); + + void initialize (); + +public: + lua_State* L; +}; + +#endif +#endif +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/Context.h b/src/Context.h index dfd1ba279..d7a202f99 100644 --- a/src/Context.h +++ b/src/Context.h @@ -36,6 +36,7 @@ #include "Task.h" #include "TDB.h" #include "StringTable.h" +#include "Hooks.h" class Context { @@ -89,6 +90,7 @@ public: std::map aliases; std::vector tagAdditions; std::vector tagRemovals; + Hooks hooks; private: std::vector headers; diff --git a/src/Hooks.cpp b/src/Hooks.cpp new file mode 100644 index 000000000..46bd1ea69 --- /dev/null +++ b/src/Hooks.cpp @@ -0,0 +1,40 @@ +//////////////////////////////////////////////////////////////////////////////// +// task - a command line task list manager. +// +// Copyright 2006 - 2010, Paul Beckingham. +// All rights reserved. +// +// This program 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 2 of the License, or (at your option) any later +// version. +// +// This program 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 +// this program; if not, write to the +// +// Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, +// Boston, MA +// 02110-1301 +// USA +// +//////////////////////////////////////////////////////////////////////////////// + +#include "Hooks.h" + +//////////////////////////////////////////////////////////////////////////////// +Hooks::Hooks () +{ +} + +//////////////////////////////////////////////////////////////////////////////// +Hooks::~Hooks () +{ +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/Hooks.h b/src/Hooks.h new file mode 100644 index 000000000..08a26fe12 --- /dev/null +++ b/src/Hooks.h @@ -0,0 +1,43 @@ +//////////////////////////////////////////////////////////////////////////////// +// task - a command line task list manager. +// +// Copyright 2006 - 2010, Paul Beckingham. +// All rights reserved. +// +// This program 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 2 of the License, or (at your option) any later +// version. +// +// This program 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 +// this program; if not, write to the +// +// Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, +// Boston, MA +// 02110-1301 +// USA +// +//////////////////////////////////////////////////////////////////////////////// +#ifndef INCLUDED_HOOKS +#define INCLUDED_HOOKS + +class Hooks +{ +public: + Hooks (); // Default constructor + ~Hooks (); // Destructor + + Hooks (const Hooks&); + Hooks& operator= (const Hooks&); + +private: +}; + +#endif +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/Makefile.am b/src/Makefile.am index 4bc6c9a73..accbed95c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,14 +1,15 @@ bin_PROGRAMS = task -task_SOURCES = Att.cpp Cmd.cpp Color.cpp Config.cpp Context.cpp Date.cpp \ - Directory.cpp Duration.cpp File.cpp Filter.cpp Grid.cpp \ - Keymap.cpp Location.cpp Nibbler.cpp Path.cpp Permission.cpp \ - Record.cpp Sequence.cpp StringTable.cpp Subst.cpp TDB.cpp \ - Table.cpp Task.cpp Timer.cpp command.cpp custom.cpp edit.cpp \ - import.cpp interactive.cpp main.cpp recur.cpp report.cpp \ - rules.cpp text.cpp util.cpp \ - Att.h Cmd.h Color.h Config.h Context.h Date.h Directory.h \ - Duration.h File.h Filter.h Grid.h Keymap.h Location.h \ - Nibbler.h Path.h Permission.h Record.h Sequence.h \ +task_SOURCES = API.cpp Att.cpp Cmd.cpp Color.cpp Config.cpp Context.cpp \ + Date.cpp Directory.cpp Duration.cpp File.cpp Filter.cpp \ + Grid.cpp Hooks.cpp Keymap.cpp Location.cpp Nibbler.cpp \ + Path.cpp Permission.cpp Record.cpp Sequence.cpp \ + StringTable.cpp Subst.cpp TDB.cpp Table.cpp Task.cpp Timer.cpp \ + command.cpp custom.cpp edit.cpp import.cpp interactive.cpp \ + main.cpp recur.cpp report.cpp rules.cpp text.cpp util.cpp \ + API.h Att.h Cmd.h Color.h Config.h Context.h Date.h \ + Directory.h Duration.h File.h Filter.h Grid.h Hooks.h Keymap.h \ + Location.h Nibbler.h Path.h Permission.h Record.h Sequence.h \ StringTable.h Subst.h TDB.h Table.h Task.h Timer.h i18n.h \ main.h text.h util.h - +task_CPPFLAGS=$(LUA_CFLAGS) +task_LDFLAGS=$(LUA_LFLAGS) diff --git a/with_lua b/with_lua new file mode 100755 index 000000000..5b24f5e97 --- /dev/null +++ b/with_lua @@ -0,0 +1,6 @@ +# This is currently what is required to build with Lua. + +#./configure --enable-lua=yes --with-lua --with-lua-inc=/usr/local/include --with-lua-lib=/usr/local/lib +#./configure --enable-lua --with-lua --with-lua-inc=/usr/local/include --with-lua-lib=/usr/local/lib + ./configure --enable-lua --with-lua-inc=/usr/local/include --with-lua-lib=/usr/local/lib +