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