1 /*
2 	This is part of TeXworks, an environment for working with TeX documents
3 	Copyright (C) 2010-2013  Jonathan Kew, Stefan Löffler, Charlie Sharpsteen
4 
5 	This program is free software; you can redistribute it and/or modify
6 	it under the terms of the GNU General Public License as published by
7 	the Free Software Foundation; either version 2 of the License, or
8 	(at your option) any later version.
9 
10 	This program is distributed in the hope that it will be useful,
11 	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 	GNU General Public License for more details.
14 
15 	You should have received a copy of the GNU General Public License
16 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 	For links to further information, or to contact the authors,
19 	see <http://www.tug.org/texworks/>.
20 */
21 
22 #ifndef TW_LUA_PLUGIN_H
23 #define TW_LUA_PLUGIN_H
24 
25 #include "TWScript.h"
26 
27 #include "lua.hpp"
28 
29 #include <QMetaMethod>
30 #include <QMetaProperty>
31 #include <QVariant>
32 
33 /** \brief Implementation of the script plugin interface */
34 class TWLuaPlugin : public QObject, public TWScriptLanguageInterface
35 {
36 	Q_OBJECT
37 	Q_INTERFACES(TWScriptLanguageInterface)
38 #if QT_VERSION >= 0x050000
39 	Q_PLUGIN_METADATA(IID "org.tug.texworks.ScriptPlugins.LuaPlugin")
40 #endif
41 
42 public:
43 	/** \brief Constructor
44 	 *
45 	 * Initializes the lua state
46 	 */
47 	TWLuaPlugin();
48 
49 	/** \brief Destructor
50 	 *
51 	 * Closes the lua state
52 	 */
53 	virtual ~TWLuaPlugin();
54 
55 	/** \brief Script factory
56 	 *
57 	 * \return	pointer to a new LuaScript object cast to TWScript as the
58 	 * 			interface requires; the caller owns the object and must delete
59 	 * 			it.
60 	 */
61 	virtual TWScript* newScript(const QString& fileName);
62 
63 	/** \brief	Get the supported script language name
64 	 *
65 	 * \return	the name of the scripting language
66 	 */
scriptLanguageName()67 	virtual QString scriptLanguageName() const { return QString("Lua"); }
68 
69 	/** \brief	Get a URL for information on the supported script language
70 	 *
71 	 * \return	a string with a URL for information about the language
72 	 */
scriptLanguageURL()73 	virtual QString scriptLanguageURL() const { return QString("http://www.lua.org/"); }
74 
75     /** \brief  Return whether the given file is handled by this scripting language plugin
76 	 */
canHandleFile(const QFileInfo & fileInfo)77 	virtual bool canHandleFile(const QFileInfo& fileInfo) const { return fileInfo.suffix() == QString("lua"); }
78 
getLuaState()79 	lua_State * getLuaState() { return luaState; }
80 
81 protected:
82 	lua_State * luaState;	///< property to hold the lua state
83 };
84 
85 /** \brief Class for handling lua scripts */
86 class LuaScript : public TWScript
87 {
88 	Q_OBJECT
Q_INTERFACES(TWScript)89 	Q_INTERFACES(TWScript)
90 
91 public:
92 	/** \brief Constructor
93 	 *
94 	 * Initializes m_LuaPlugin
95 	 * \param	lua	pointer to the plugin that holds the lua state to operate on
96 	 */
97 	LuaScript(TWLuaPlugin* lua, const QString& fileName) : TWScript(lua, fileName), m_LuaPlugin(lua) { }
98 
99 	/** \brief Parse the script header
100 	 *
101 	 * \return	\c true if successful, \c false if not (e.g. because the file
102 	 * 			is no valid Tw lua script)
103 	 */
parseHeader()104 	virtual bool parseHeader() { return doParseHeader("--[[", "]]", ""); }
105 
106 protected:
107 	/** \brief Run the lua script
108 	 *
109 	 * \param	tw	the TW interface object, exposed to the script as the TW global
110 	 *
111 	 * \return	\c true on success, \c false if an error occured
112 	 */
113 	virtual bool execute(TWScriptAPI *tw) const;
114 
115 	/** \brief Convenience function to wrap a QObject and push it onto the stack
116 	 *
117 	 * \param	L	the lua state to operate on
118 	 * \param	obj	the QObject to expose to python
119 	 * \param	throwError	currently unused
120 	 * \return	the number of values pushed onto the stack; 1 on success, 0 on
121 	 * 			failure
122 	 */
123 	static int pushQObject(lua_State * L, QObject * obj, const bool throwError = true);
124 
125 	/** \brief Convenience function to convert a QVariant and push it onto the stack
126 	 *
127 	 * \note	QList will be converted to lua tables with numeric, one-based
128 	 * 			indices.
129 	 * \param	L	the lua state to operate on
130 	 * \param	v	the QVariant to convert and push
131 	 * \param	throwError	if \c true, luaL_error is used to report errors;
132 	 * 				this should only be used in protected mode (i.e. from inside
133 	 * 				the lua engine, as it could cause Tw to crash otherwise)
134 	 * \return	the number of values pushed onto the stack; 1 on success, 0 on
135 	 * 			failure
136 	 */
137 	static int pushVariant(lua_State * L, const QVariant & v, const bool throwError = true);
138 
139 	/** \brief Convenience function to convert a stack value to a QVariant
140 	 *
141 	 * \note	Tables with only numeric, consecutive, one-based indices will be
142 	 * 			converted to QList. If the value can't be converted, an error is
143 	 * 			raised and an empty QVariant is returned.
144 	 * \param	L	the lua state to operate on
145 	 * \param	idx	the index of the value on the stack (may be negative)
146 	 * \param	throwError	if \c true, luaL_error is used to report errors;
147 	 * 				this should only be used in protected mode (i.e. from inside
148 	 * 				the lua engine, as it could cause Tw to crash otherwise)
149 	 * \return	the QVariant
150 	 */
151 	static QVariant getLuaStackValue(lua_State * L, int idx, const bool throwError = true);
152 
153 	/** \brief Handler for property requests on QObjects
154 	 *
155 	 * On success, the value of the property is pushed onto the stack
156 	 * \note	The QObject* must be supplied as first upvalue.
157 	 * \param	L	the lua state to operate on
158 	 * \return	the number of values pushed onto the stack; 1 on success, 0 on
159 	 * 			failure
160 	 */
161 	static int getProperty(lua_State * L);
162 
163 	/** \brief Handler for setting attribute values on QObjects
164 	 *
165 	 * \note	The QObject* must be supplied as first upvalue.
166 	 * \param	L	the lua state to operate on
167 	 * \return	0 (the number of values pushed onto the stack)
168 	 */
169 	static int setProperty(lua_State * L);
170 
171 	/** \brief Handler for calling methods of QObjects
172 	 *
173 	 * \note	The QObject* must be supplied as first upvalue and the method
174 	 * 			name as second upvalue.
175 	 * \note	For void methods, nil is pushed onto the stack
176 	 * \param	L	the lua state to operate on
177 	 * \return	the number of values pushed onto the stack; 1 on success, 0 on
178 	 * 			failure
179 	 */
180 	static int callMethod(lua_State * L);
181 
182 	TWLuaPlugin * m_LuaPlugin;	///< pointer to the lua plugin holding the lua state
183 };
184 
185 #endif // !defined(TW_LUA_PLUGIN_H)
186