mirror of
https://github.com/koreader/koreader
synced 2024-10-31 21:20:20 +00:00
Support configurable extra plugin lookup path (#2693)
* 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. * build(fix): also purge non-exist plugins on build * plugin: migrate debug plugin to menu sorter
This commit is contained in:
parent
ba74921c4b
commit
1461574894
3
Makefile
3
Makefile
@ -79,6 +79,9 @@ endif
|
|||||||
@echo "[*] Install plugins"
|
@echo "[*] Install plugins"
|
||||||
@# TODO: link istead of cp?
|
@# TODO: link istead of cp?
|
||||||
$(RCP) plugins/* $(INSTALL_DIR)/koreader/plugins/
|
$(RCP) plugins/* $(INSTALL_DIR)/koreader/plugins/
|
||||||
|
@# purge deleted plugins
|
||||||
|
for d in $$(ls $(INSTALL_DIR)/koreader/plugins); do \
|
||||||
|
test -d plugins/$$d || rm -rf $(INSTALL_DIR)/koreader/plugins/$$d ; done
|
||||||
@echo "[*] Installresources"
|
@echo "[*] Installresources"
|
||||||
$(RCP) -pL resources/fonts/* $(INSTALL_DIR)/koreader/fonts/
|
$(RCP) -pL resources/fonts/* $(INSTALL_DIR)/koreader/fonts/
|
||||||
install -d $(INSTALL_DIR)/koreader/{screenshots,data/{dict,tessdata},fonts/host,ota}
|
install -d $(INSTALL_DIR)/koreader/{screenshots,data/{dict,tessdata},fonts/host,ota}
|
||||||
|
@ -1,42 +1,66 @@
|
|||||||
local lfs = require("libs/libkoreader-lfs")
|
local lfs = require("libs/libkoreader-lfs")
|
||||||
local logger = require("logger")
|
local logger = require("logger")
|
||||||
|
|
||||||
local PluginLoader = {
|
local DEFAULT_PLUGIN_PATH = "plugins"
|
||||||
plugin_path = "plugins"
|
|
||||||
}
|
local PluginLoader = {}
|
||||||
|
|
||||||
function PluginLoader:loadPlugins()
|
function PluginLoader:loadPlugins()
|
||||||
if self.plugins then return self.plugins end
|
if self.plugins then return self.plugins end
|
||||||
|
|
||||||
self.plugins = {}
|
self.plugins = {}
|
||||||
for f in lfs.dir(self.plugin_path) do
|
local lookup_path_list = { DEFAULT_PLUGIN_PATH }
|
||||||
local path = self.plugin_path.."/"..f
|
local extra_paths = G_reader_settings:readSetting("extra_plugin_paths")
|
||||||
local mode = lfs.attributes(path, "mode")
|
if extra_paths then
|
||||||
-- valid koreader plugin directory
|
if type(extra_paths) == "string" then
|
||||||
if mode == "directory" and f:find(".+%.koplugin$") then
|
extra_paths = { extra_paths }
|
||||||
local mainfile = path.."/".."main.lua"
|
end
|
||||||
local package_path = package.path
|
if type(extra_paths) == "table" then
|
||||||
local package_cpath = package.cpath
|
for _,extra_path in ipairs(extra_paths) do
|
||||||
package.path = path.."/?.lua;"..package.path
|
local extra_path_mode = lfs.attributes(extra_path, "mode")
|
||||||
package.cpath = path.."/lib/?.so;"..package.cpath
|
if extra_path_mode == "directory" and extra_path ~= DEFAULT_PLUGIN_PATH then
|
||||||
local ok, plugin_module = pcall(dofile, mainfile)
|
table.insert(lookup_path_list, extra_path)
|
||||||
if not ok or not plugin_module then
|
end
|
||||||
logger.warn("Error when loading", mainfile, plugin_module)
|
end
|
||||||
elseif type(plugin_module.disabled) ~= "boolean" or not plugin_module.disabled then
|
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.path = package_path
|
||||||
package.cpath = package_cpath
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- set package path for all loaded plugins
|
||||||
for _,plugin in ipairs(self.plugins) do
|
for _,plugin in ipairs(self.plugins) do
|
||||||
package.path = package.path..";"..plugin.path.."/?.lua"
|
package.path = string.format("%s;%s/?.lua", package.path, plugin.path)
|
||||||
package.cpath = package.cpath..";"..plugin.path.."/lib/?.so"
|
package.cpath = string.format("%s;%s/lib/?.so", package.cpath, plugin.path)
|
||||||
end
|
end
|
||||||
|
|
||||||
table.sort(self.plugins, function(v1,v2) return v1.path < v2.path end)
|
table.sort(self.plugins, function(v1,v2) return v1.path < v2.path end)
|
||||||
|
@ -23,7 +23,6 @@ local order = {
|
|||||||
"highlight_options",
|
"highlight_options",
|
||||||
"change_font",
|
"change_font",
|
||||||
"hyphenation",
|
"hyphenation",
|
||||||
"read_timer",
|
|
||||||
},
|
},
|
||||||
setting = {
|
setting = {
|
||||||
"read_from_right_to_left",
|
"read_from_right_to_left",
|
||||||
@ -43,6 +42,7 @@ local order = {
|
|||||||
"status_bar",
|
"status_bar",
|
||||||
},
|
},
|
||||||
tools = {
|
tools = {
|
||||||
|
"read_timer",
|
||||||
"calibre_wireless_connection",
|
"calibre_wireless_connection",
|
||||||
"evernote",
|
"evernote",
|
||||||
"goodreads",
|
"goodreads",
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
local InfoMessage = require("ui/widget/infomessage")
|
-- This is a debug plugin, remove the following if block to enable it
|
||||||
|
if true then
|
||||||
|
return { disabled = true, }
|
||||||
|
end
|
||||||
|
|
||||||
|
local InfoMessage = require("ui/widget/infomessage") -- luacheck:ignore
|
||||||
local UIManager = require("ui/uimanager")
|
local UIManager = require("ui/uimanager")
|
||||||
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
||||||
local _ = require("gettext")
|
local _ = require("gettext")
|
||||||
@ -6,22 +11,21 @@ local _ = require("gettext")
|
|||||||
local Hello = WidgetContainer:new{
|
local Hello = WidgetContainer:new{
|
||||||
name = 'Hello',
|
name = 'Hello',
|
||||||
is_doc_only = false,
|
is_doc_only = false,
|
||||||
disabled = true, -- This is a debug plugin
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function Hello:init()
|
function Hello:init()
|
||||||
self.ui.menu:registerToMainMenu(self)
|
self.ui.menu:registerToMainMenu(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Hello:addToMainMenu(tab_item_table)
|
function Hello:addToMainMenu(menu_items)
|
||||||
table.insert(tab_item_table.plugins, {
|
menu_items.hello_world = {
|
||||||
text = _("Hello World"),
|
text = _("Hello World"),
|
||||||
callback = function()
|
callback = function()
|
||||||
UIManager:show(InfoMessage:new{
|
UIManager:show(InfoMessage:new{
|
||||||
text = _("Hello, docless plugin world"),
|
text = _("Hello, plugin world"),
|
||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
})
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
return Hello
|
return Hello
|
||||||
|
@ -9,7 +9,6 @@ local ConfirmBox = require("ui/widget/confirmbox")
|
|||||||
local ImageWidget = require("ui/widget/imagewidget")
|
local ImageWidget = require("ui/widget/imagewidget")
|
||||||
local InfoMessage = require("ui/widget/infomessage")
|
local InfoMessage = require("ui/widget/infomessage")
|
||||||
local Notification = require("ui/widget/notification")
|
local Notification = require("ui/widget/notification")
|
||||||
local PluginLoader = require("pluginloader")
|
|
||||||
local Screen = require("device").screen
|
local Screen = require("device").screen
|
||||||
local UIManager = require("ui/uimanager")
|
local UIManager = require("ui/uimanager")
|
||||||
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
local WidgetContainer = require("ui/widget/container/widgetcontainer")
|
||||||
@ -165,7 +164,7 @@ function KoboLight:addToMainMenu(menu_items)
|
|||||||
text = _("Frontlight gesture controller"),
|
text = _("Frontlight gesture controller"),
|
||||||
callback = function()
|
callback = function()
|
||||||
local image = ImageWidget:new{
|
local image = ImageWidget:new{
|
||||||
file = PluginLoader.plugin_path .. "/kobolight.koplugin/demo.png",
|
file = self.path .. "/demo.png",
|
||||||
height = Screen:getHeight(),
|
height = Screen:getHeight(),
|
||||||
width = Screen:getWidth(),
|
width = Screen:getWidth(),
|
||||||
scale_factor = 0,
|
scale_factor = 0,
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
local Device = require("device")
|
local Device = require("device")
|
||||||
|
|
||||||
local command
|
local command
|
||||||
|
Loading…
Reference in New Issue
Block a user