summaryrefslogtreecommitdiff
path: root/loaders/lua5.1/peas-lua-internal.lua
diff options
context:
space:
mode:
Diffstat (limited to 'loaders/lua5.1/peas-lua-internal.lua')
-rw-r--r--loaders/lua5.1/peas-lua-internal.lua162
1 files changed, 162 insertions, 0 deletions
diff --git a/loaders/lua5.1/peas-lua-internal.lua b/loaders/lua5.1/peas-lua-internal.lua
new file mode 100644
index 0000000..8f4e60d
--- /dev/null
+++ b/loaders/lua5.1/peas-lua-internal.lua
@@ -0,0 +1,162 @@
+--
+-- Copyright (C) 2015 - Garrett Regier
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU Library 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 Library General Public License for more details.
+--
+-- You should have received a copy of the GNU Library 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.
+
+local debug = require 'debug'
+local package = require 'package'
+
+local lgi = require 'lgi'
+local GObject = lgi.GObject
+local Peas = lgi.Peas
+
+
+local Hooks = {}
+Hooks.__index = Hooks
+
+function Hooks.new()
+ local self = { priv = {} }
+ setmetatable(self, Hooks)
+
+ self.priv.module_cache = {}
+ self.priv.extension_cache = {}
+ return self
+end
+
+function Hooks:failed(msg)
+ -- This is implemented by the plugin loader
+ error('Hooks:failed() was not implemented!')
+end
+
+local function add_package_path(package_path)
+ local paths = (';%s/?.lua;%s/?/init.lua'):format(package_path,
+ package_path)
+
+ if not package.path:find(paths, 1, true) then
+ package.path = package.path .. paths
+ end
+end
+
+local function format_plugin_exception(err)
+ -- Format the error even if given a userdata
+ local formatted = debug.traceback(tostring(err), 2)
+
+ if type(formatted) ~= 'string' then
+ return formatted
+ end
+
+ -- Remove all mentions of this file
+ local lines = {}
+ for line in formatted:gmatch('([^\n]+\n?)') do
+ if line:find('peas-lua-internal.lua', 1, true) then
+ break
+ end
+
+ table.insert(lines, line)
+ end
+
+ return table.concat(lines, '')
+end
+
+function Hooks:load(filename, module_dir, module_name)
+ local module = self.priv.module_cache[filename]
+
+ if module ~= nil then
+ return module ~= false
+ end
+
+ if package.loaded[module_name] ~= nil then
+ local msg = ("Error loading plugin '%s': " ..
+ "module name '%s' has already been used")
+ self:failed(msg:format(filename, module_name))
+ end
+
+ add_package_path(module_dir)
+
+ local success, result = xpcall(function()
+ return require(module_name)
+ end, format_plugin_exception)
+
+ if not success then
+ local msg = "Error loading plugin '%s':\n%s"
+ self:failed(msg:format(module_name, tostring(result)))
+ end
+
+ if type(result) ~= 'table' then
+ self.priv.module_cache[filename] = false
+
+ local msg = "Error loading plugin '%s': expected table, got: %s (%s)"
+ self:failed(msg:format(module_name, type(result), tostring(result)))
+ end
+
+ self.priv.module_cache[filename] = result
+ self.priv.extension_cache[filename] = {}
+ return true
+end
+
+function Hooks:find_extension_type(filename, gtype)
+ local module_gtypes = self.priv.extension_cache[filename]
+ local extension_type = module_gtypes[gtype]
+
+ if extension_type ~= nil then
+ if extension_type == false then
+ return nil
+ end
+
+ return extension_type
+ end
+
+ for _, value in pairs(self.priv.module_cache[filename]) do
+ local value_gtype = value._gtype
+
+ if value_gtype ~= nil then
+ if GObject.type_is_a(value_gtype, gtype) then
+ module_gtypes[gtype] = value_gtype
+ return value_gtype
+ end
+ end
+ end
+
+ module_gtypes[gtype] = false
+ return nil
+end
+
+local function check_native(native, wrapped, typename)
+ local msg = ('Invalid wrapper for %s: %s'):format(typename,
+ tostring(wrapped))
+
+ -- Cannot compare userdata directly!
+ assert(wrapped ~= nil, msg)
+ assert(tostring(native) == tostring(wrapped._native), msg)
+end
+
+function Hooks:setup_extension(exten, info)
+ local wrapped_exten = GObject.Object(exten, false)
+ check_native(exten, wrapped_exten, 'extension')
+
+ local wrapped_info = Peas.PluginInfo(info, false)
+ check_native(info, wrapped_info, 'PeasPluginInfo')
+
+ wrapped_exten.priv.plugin_info = wrapped_info
+end
+
+function Hooks:garbage_collect()
+ collectgarbage()
+end
+
+return Hooks.new()
+
+-- ex:set ts=4 et sw=4 ai: