From 0bc825a0b39b3b278ca1465f62acd48f5c3c6255 Mon Sep 17 00:00:00 2001 From: Qingping Hou Date: Tue, 28 Mar 2017 19:32:20 -0700 Subject: [PATCH] plugin loader(feat): support loading plugins from user defined directories Extra plugin lookup paths can be set in global reader setting via key extra_plugin_paths. Value of the key can either be a string or an array of strings. --- frontend/pluginloader.lua | 72 +++++++++++++++++++---------- plugins/kobolight.koplugin/main.lua | 3 +- plugins/timesync.koplugin/main.lua | 1 - 3 files changed, 49 insertions(+), 27 deletions(-) diff --git a/frontend/pluginloader.lua b/frontend/pluginloader.lua index fa39a3352a30..1548e6b7084d 100644 --- a/frontend/pluginloader.lua +++ b/frontend/pluginloader.lua @@ -1,42 +1,66 @@ local lfs = require("libs/libkoreader-lfs") local logger = require("logger") -local PluginLoader = { - plugin_path = "plugins" -} +local DEFAULT_PLUGIN_PATH = "plugins" + +local PluginLoader = {} function PluginLoader:loadPlugins() if self.plugins then return self.plugins end self.plugins = {} - for f in lfs.dir(self.plugin_path) do - local path = self.plugin_path.."/"..f - local mode = lfs.attributes(path, "mode") - -- valid koreader plugin directory - if mode == "directory" and f:find(".+%.koplugin$") then - local mainfile = path.."/".."main.lua" - local package_path = package.path - local package_cpath = package.cpath - package.path = path.."/?.lua;"..package.path - package.cpath = path.."/lib/?.so;"..package.cpath - local ok, plugin_module = pcall(dofile, mainfile) - if not ok or not plugin_module then - logger.warn("Error when loading", mainfile, plugin_module) - elseif type(plugin_module.disabled) ~= "boolean" or not plugin_module.disabled then + local lookup_path_list = { DEFAULT_PLUGIN_PATH } + local extra_paths = G_reader_settings:readSetting("extra_plugin_paths") + if extra_paths then + if type(extra_paths) == "string" then + extra_paths = { extra_paths } + end + if type(extra_paths) == "table" then + for _,extra_path in ipairs(extra_paths) do + local extra_path_mode = lfs.attributes(extra_path, "mode") + if extra_path_mode == "directory" and extra_path ~= DEFAULT_PLUGIN_PATH then + table.insert(lookup_path_list, extra_path) + end + end + else + logger.err("extra_plugin_paths config only accepts string or table value") + end + end + + -- keep reference to old value so they can be restored later + local package_path = package.path + local package_cpath = package.cpath + + for _,lookup_path in ipairs(lookup_path_list) do + logger.info('Loading plugins from directory:', lookup_path) + for entry in lfs.dir(lookup_path) do + local plugin_root = lookup_path.."/"..entry + local mode = lfs.attributes(plugin_root, "mode") + -- valid koreader plugin directory + if mode == "directory" and entry:find(".+%.koplugin$") then + local mainfile = plugin_root.."/main.lua" + package.path = string.format("%s/?.lua;%s", plugin_root, package_path) + package.cpath = string.format("%s/lib/?.so;%s", plugin_root, package_cpath) + local ok, plugin_module = pcall(dofile, mainfile) + if not ok or not plugin_module then + logger.warn("Error when loading", mainfile, plugin_module) + elseif type(plugin_module.disabled) ~= "boolean" or not plugin_module.disabled then + plugin_module.path = plugin_root + plugin_module.name = plugin_module.name or plugin_root:match("/(.-)%.koplugin") + table.insert(self.plugins, plugin_module) + else + logger.info("Plugin ", mainfile, " has been disabled.") + end package.path = package_path package.cpath = package_cpath - plugin_module.path = path - plugin_module.name = plugin_module.name or path:match("/(.-)%.koplugin") - table.insert(self.plugins, plugin_module) - else - logger.info("Plugin ", mainfile, " has been disabled.") end end end + -- set package path for all loaded plugins for _,plugin in ipairs(self.plugins) do - package.path = package.path..";"..plugin.path.."/?.lua" - package.cpath = package.cpath..";"..plugin.path.."/lib/?.so" + package.path = string.format("%s;%s/?.lua", package.path, plugin.path) + package.cpath = string.format("%s;%s/lib/?.so", package.cpath, plugin.path) end table.sort(self.plugins, function(v1,v2) return v1.path < v2.path end) diff --git a/plugins/kobolight.koplugin/main.lua b/plugins/kobolight.koplugin/main.lua index 6f94aa385790..6ff30ac744e4 100644 --- a/plugins/kobolight.koplugin/main.lua +++ b/plugins/kobolight.koplugin/main.lua @@ -9,7 +9,6 @@ local ConfirmBox = require("ui/widget/confirmbox") local ImageWidget = require("ui/widget/imagewidget") local InfoMessage = require("ui/widget/infomessage") local Notification = require("ui/widget/notification") -local PluginLoader = require("pluginloader") local Screen = require("device").screen local UIManager = require("ui/uimanager") local WidgetContainer = require("ui/widget/container/widgetcontainer") @@ -165,7 +164,7 @@ function KoboLight:addToMainMenu(menu_items) text = _("Frontlight gesture controller"), callback = function() local image = ImageWidget:new{ - file = PluginLoader.plugin_path .. "/kobolight.koplugin/demo.png", + file = self.path .. "/demo.png", height = Screen:getHeight(), width = Screen:getWidth(), scale_factor = 0, diff --git a/plugins/timesync.koplugin/main.lua b/plugins/timesync.koplugin/main.lua index 7c0084c753e6..5d4f934420f3 100644 --- a/plugins/timesync.koplugin/main.lua +++ b/plugins/timesync.koplugin/main.lua @@ -1,4 +1,3 @@ - local Device = require("device") local command