Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support configurable extra plugin lookup path #2693

Merged
merged 5 commits into from
Apr 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ endif
@echo "[*] Install plugins"
@# TODO: link istead of cp?
$(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"
$(RCP) -pL resources/fonts/* $(INSTALL_DIR)/koreader/fonts/
install -d $(INSTALL_DIR)/koreader/{screenshots,data/{dict,tessdata},fonts/host,ota}
Expand Down
72 changes: 48 additions & 24 deletions frontend/pluginloader.lua
Original file line number Diff line number Diff line change
@@ -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")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we directly add DataStorage:getDataDir()/plugins/ to this list.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually don't really expect many people to use this feature right now. We can always add a default path to the list if it turns out to be a popular feature. My preference is to not introduce this extra lookup overhead to all users for now.

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)
Expand Down
2 changes: 1 addition & 1 deletion frontend/ui/elements/reader_menu_order.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ local order = {
"highlight_options",
"change_font",
"hyphenation",
"read_timer",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to prefer this plugin to be placed in tools? IMO, it's more like a "reading experience".

Copy link
Member

@Frenzie Frenzie Mar 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does seem a touch out of place with the other rendering options. There should at least be a separator in between if it goes in the typeset menu. I didn't want to make things controversial by changing the menu around (and I didn't have time to think about it anyway) but it should be something more like

        -- rendering stuff
        "page_overlap",
        "switch_zoom_mode",
        "set_render_style",
        --sep, I don't think highlight options go with anything else really
        "highlight_options",
        --sep, font-related (typeset) stuff
        "change_font",
        "floating_punctuation",
        "hyphenation",
        --sep, "reading experience" stuff
        "read_timer"
        --speed reading?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Firstly, for consistent reason. It's placed under tools tab in filemanager. We should either keep it consistent between apps or only enable it in reader.

Secondly, that tab is named typeset, which means anything that controls rendering results. A timer doesn't fit into this category. With the new UX proposed by @baskerville and the new separator feature, we can combine navigation and typeset into one read menu, then it makes more sense to put timer there.

},
setting = {
"read_from_right_to_left",
Expand All @@ -43,6 +42,7 @@ local order = {
"status_bar",
},
tools = {
"read_timer",
"calibre_wireless_connection",
"evernote",
"goodreads",
Expand Down
16 changes: 10 additions & 6 deletions plugins/hello.koplugin/main.lua
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
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 WidgetContainer = require("ui/widget/container/widgetcontainer")
local _ = require("gettext")

local Hello = WidgetContainer:new{
name = 'Hello',
is_doc_only = false,
disabled = true, -- This is a debug plugin
}

function Hello:init()
self.ui.menu:registerToMainMenu(self)
end

function Hello:addToMainMenu(tab_item_table)
table.insert(tab_item_table.plugins, {
function Hello:addToMainMenu(menu_items)
menu_items.hello_world = {
text = _("Hello World"),
callback = function()
UIManager:show(InfoMessage:new{
text = _("Hello, docless plugin world"),
text = _("Hello, plugin world"),
})
end,
})
}
end

return Hello
3 changes: 1 addition & 2 deletions plugins/kobolight.koplugin/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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,
Expand Down
1 change: 0 additions & 1 deletion plugins/timesync.koplugin/main.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

local Device = require("device")

local command
Expand Down