Terminal: add shortcuts for re-useable commands (#6609)

To be able to quickly repeat often used terminal commands
reviewable/pr6623/r1
smartscripts-nl 4 years ago committed by GitHub
parent f15aa7103f
commit 20ddad2951
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -77,7 +77,7 @@ local settingsList = {
calibre_search = { category="none", event="CalibreSearch", title=_("Search in calibre metadata"), device=true,},
calibre_browse_tags = { category="none", event="CalibreBrowseTags", title=_("Browse all calibre tags"), device=true,},
calibre_browse_series = { category="none", event="CalibreBrowseSeries", title=_("Browse all calibre series"), device=true, separator=true,},
edit_last_edited_file = { category = "none", event = "OpenLastEditedFile", title = 'Texteditor: open last file', device = true, separator = true, },
edit_last_edited_file = { category = "none", event = "OpenLastEditedFile", title = _("Texteditor: open last file"), device = true, separator = true, },
favorites = { category="none", event="ShowColl", arg="favorites", title=_("Favorites"), device=true,},
-- filemanager settings

@ -1,7 +1,13 @@
local ButtonDialog = require("ui/widget/buttondialog")
local CenterContainer = require("ui/widget/container/centercontainer")
local DataStorage = require("datastorage")
local Font = require("ui/font")
local InfoMessage = require("ui/widget/infomessage")
local InputDialog = require("ui/widget/inputdialog")
local LuaSettings = require("luasettings")
local Menu = require("ui/widget/menu")
local Screen = require("device").screen
local T = require("ffi/util").template
local TextViewer = require("ui/widget/textviewer")
local Trapper = require("ui/trapper")
local UIManager = require("ui/uimanager")
@ -9,49 +15,388 @@ local WidgetContainer = require("ui/widget/container/widgetcontainer")
local logger = require("logger")
local util = require("ffi/util")
local _ = require("gettext")
local Screen = require("device").screen
local Terminal = WidgetContainer:new{
name = "terminal",
dump_file = util.realpath(DataStorage:getDataDir()) .. "/terminal_output.txt",
command = "",
dump_file = util.realpath(DataStorage:getDataDir()) .. "/terminal_output.txt",
items_per_page = G_reader_settings:readSetting("items_per_page") or 16,
settings = LuaSettings:open(DataStorage:getSettingsDir() .. "/terminal_shortcuts.lua"),
shortcuts_dialog = nil,
shortcuts_menu = nil,
-- shortcuts_file = DataStorage:getSettingsDir() .. "/terminal_shortcuts.lua",
shortcuts = {},
source = "terminal",
}
function Terminal:init()
self.ui.menu:registerToMainMenu(self)
self.shortcuts = self.settings:readSetting("shortcuts") or {}
end
function Terminal:saveShortcuts()
self.settings:saveSetting("shortcuts", self.shortcuts)
self.settings:flush()
UIManager:show(InfoMessage:new{
text = _("Shortcuts saved"),
timeout = 2
})
end
function Terminal:manageShortcuts()
self.shortcuts_dialog = CenterContainer:new {
dimen = Screen:getSize(),
}
self.shortcuts_menu = Menu:new{
show_parent = self.ui,
width = Screen:getWidth(),
height = Screen:getHeight(),
covers_fullscreen = true, -- hint for UIManager:_repaint()
is_borderless = true,
is_popout = false,
perpage = self.items_per_page,
onMenuHold = self.onMenuHoldShortcuts,
_manager = self,
}
table.insert(self.shortcuts_dialog, self.shortcuts_menu)
self.shortcuts_menu.close_callback = function()
UIManager:close(self.shortcuts_dialog)
end
-- sort the shortcuts:
if #self.shortcuts > 0 then
table.sort(self.shortcuts, function(v1, v2)
return v1.text < v2.text
end)
end
self:updateItemTable()
end
function Terminal:updateItemTable()
local item_table = {}
if #self.shortcuts > 0 then
local actions_count = 3 -- separator + actions
for nr, f in ipairs(self.shortcuts) do
local item = {
nr = nr,
text = f.text,
commands = f.commands,
editable = true,
deletable = true,
callback = function()
-- so we know which middle button to display in the results:
self.source = "shortcut"
-- execute immediately, skip terminal dialog:
self.command = self:ensureWhitelineAfterCommands(f.commands)
Trapper:wrap(function()
self:execute()
end)
end
}
table.insert(item_table, item)
-- add page actions at end of each page with shortcuts:
local factor = self.items_per_page - actions_count
if nr % factor == 0 or nr == #self.shortcuts then
-- insert "separator":
table.insert(item_table, {
text = " ",
deletable = false,
editable = false,
callback = function()
self:manageShortcuts()
end,
})
-- actions:
self:insertPageActions(item_table)
end
end
-- no shortcuts defined yet:
else
self:insertPageActions(item_table)
end
local title = #self.shortcuts == 1 and _("Terminal shortcut") or _("Terminal shortcuts")
self.shortcuts_menu:switchItemTable(tostring(#self.shortcuts) .. " " .. title, item_table)
UIManager:show(self.shortcuts_dialog)
end
function Terminal:insertPageActions(item_table)
table.insert(item_table, {
text = " " .. _("to terminal…"),
deletable = false,
editable = false,
callback = function()
self:terminal()
end,
})
table.insert(item_table, {
text = " " .. _("close…"),
deletable = false,
editable = false,
callback = function()
return false
end,
})
end
function Terminal:onMenuHoldShortcuts(item)
if item.deletable or item.editable then
local shortcut_shortcuts_dialog
shortcut_shortcuts_dialog = ButtonDialog:new{
buttons = {{
{
text = _("Edit name"),
enabled = item.editable,
callback = function()
UIManager:close(shortcut_shortcuts_dialog)
if self._manager.shortcuts_dialog ~= nil then
UIManager:close(self._manager.shortcuts_dialog)
self._manager.shortcuts_dialog = nil
end
self._manager:editName(item)
end
},
{
text = _("Edit commands"),
enabled = item.editable,
callback = function()
UIManager:close(shortcut_shortcuts_dialog)
if self._manager.shortcuts_dialog ~= nil then
UIManager:close(self._manager.shortcuts_dialog)
self._manager.shortcuts_dialog = nil
end
self._manager:editCommands(item)
end
},
},
{
{
text = _("Copy"),
enabled = item.editable,
callback = function()
UIManager:close(shortcut_shortcuts_dialog)
if self._manager.shortcuts_dialog ~= nil then
UIManager:close(self._manager.shortcuts_dialog)
self._manager.shortcuts_dialog = nil
end
self._manager:copyCommands(item)
end
},
{
text = _("Delete"),
enabled = item.deletable,
callback = function()
UIManager:close(shortcut_shortcuts_dialog)
if self._manager.shortcuts_dialog ~= nil then
UIManager:close(self._manager.shortcuts_dialog)
self._manager.shortcuts_dialog = nil
end
self._manager:deleteShortcut(item)
end
}
}}
}
UIManager:show(shortcut_shortcuts_dialog)
return true
end
end
function Terminal:copyCommands(item)
local new_item = {
text = item.text .. " (copy)",
commands = item.commands
}
table.insert(self.shortcuts, new_item)
UIManager:show(InfoMessage:new{
text = _("Shortcut copied"),
timeout = 2
})
self:saveShortcuts()
self:manageShortcuts()
end
function Terminal:editCommands(item)
local edit_dialog
edit_dialog = InputDialog:new{
title = T(_('Edit commands for "%1"'), item.text),
input = item.commands,
width = Screen:getWidth() * 0.9,
para_direction_rtl = false, -- force LTR
input_type = "string",
allow_newline = true,
cursor_at_end = true,
fullscreen = true,
buttons = {{{
text = _("Cancel"),
callback = function()
UIManager:close(edit_dialog)
edit_dialog = nil
self:manageShortcuts()
end,
}, {
text = _("Save"),
callback = function()
local input = edit_dialog:getInputText()
UIManager:close(edit_dialog)
edit_dialog = nil
if input:match("[A-Za-z]") then
self.shortcuts[item.nr]["commands"] = input
self:saveShortcuts()
self:manageShortcuts()
end
end,
}}},
}
UIManager:show(edit_dialog)
edit_dialog:onShowKeyboard()
end
function Terminal:editName(item)
local edit_dialog
edit_dialog = InputDialog:new{
title = _("Edit name"),
input = item.text,
width = Screen:getWidth() * 0.9,
para_direction_rtl = false, -- force LTR
input_type = "string",
allow_newline = false,
cursor_at_end = true,
fullscreen = true,
buttons = {{{
text = _("Cancel"),
callback = function()
UIManager:close(edit_dialog)
edit_dialog = nil
self:manageShortcuts()
end,
}, {
text = _("Save"),
callback = function()
local input = edit_dialog:getInputText()
UIManager:close(edit_dialog)
edit_dialog = nil
if input:match("[A-Za-z]") then
self.shortcuts[item.nr]["text"] = input
self:saveShortcuts()
self:manageShortcuts()
end
end,
}}},
}
UIManager:show(edit_dialog)
edit_dialog:onShowKeyboard()
end
function Terminal:deleteShortcut(item)
local shortcuts = {}
for _, element in ipairs(self.shortcuts) do
if element.text ~= item.text and element.commands ~= item.commands then
table.insert(shortcuts, element)
end
end
self.shortcuts = shortcuts
self:saveShortcuts()
self:manageShortcuts()
end
function Terminal:onTerminalStart()
-- if shortcut commands are defined, go directly to the the shortcuts manager (so we can execute scripts more quickly):
if #self.shortcuts == 0 then
self:terminal()
else
self:manageShortcuts()
end
end
function Terminal:terminal()
self.input = InputDialog:new{
title = _("Enter a command and press \"Execute\""),
input = self.command,
title = _("Enter a command and press \"Execute\""),
input = self.command:gsub("\n+$", ""),
para_direction_rtl = false, -- force LTR
text_height = math.floor(Screen:getHeight() * 0.4),
input_type = "string",
-- allow multiple lines with commands:
allow_newline = true,
cursor_at_end = true,
fullscreen = true,
buttons = {{{
text = _("Cancel"),
callback = function()
UIManager:close(self.input)
end,
}, {
text = _("Execute"),
callback = function()
UIManager:close(self.input)
Trapper:wrap(function()
self:execute()
end)
end,
}}},
text = _("Cancel"),
callback = function()
UIManager:close(self.input)
end,
}, {
text = _("Shortcuts"),
callback = function()
UIManager:close(self.input)
self:manageShortcuts()
end,
}, {
text = _("Save"),
callback = function()
local input = self.input:getInputText()
if input:match("[A-Za-z]") then
local function callback(name)
local new_shortcut = {
text = name,
commands = input,
}
table.insert(self.shortcuts, new_shortcut)
self:saveShortcuts()
end
local prompt
prompt = InputDialog:new{
title = _("Name"),
input = "",
input_type = "text",
fullscreen = true,
condensed = true,
allow_newline = false,
cursor_at_end = true,
buttons = {{{
text = _("Cancel"),
callback = function()
UIManager:close(prompt)
end,
},
{
text = _("Save"),
is_enter_default = true,
callback = function()
local newval = prompt:getInputText()
UIManager:close(prompt)
callback(newval)
end,
}}}
}
UIManager:show(prompt)
prompt:onShowKeyboard()
end
end,
}, {
text = _("Execute"),
callback = function()
UIManager:close(self.input)
-- so we know which middle button to display in the results:
self.source = "terminal"
self.command = self:ensureWhitelineAfterCommands(self.input:getInputText())
Trapper:wrap(function()
self:execute()
end)
end,
}}},
}
UIManager:show(self.input)
self.input:onShowKeyboard()
end
-- for prettier formatting of output by separating commands and result thereof with a whiteline:
function Terminal:ensureWhitelineAfterCommands(commands)
if string.sub(commands, -1) ~= "\n" then
commands = commands .. "\n"
end
return commands
end
function Terminal:execute()
self.command = self.input:getInputText()
local wait_msg = InfoMessage:new{
text = _("Executing…"),
}
@ -69,29 +414,61 @@ function Terminal:execute()
end
UIManager:close(wait_msg)
local viewer
viewer = TextViewer:new {
title = _("Command output"),
text = table.concat(entries, "\n"),
justified = false,
text_face = Font:getFace("smallinfont"),
-- support re-invoking the terminal with a button:
local buttons_table
local back_button = {
text = _("Back"),
callback = function()
UIManager:close(viewer)
if self.source == "terminal" then
self:terminal()
else
self:manageShortcuts()
end
end,
}
local close_button = {
text = _("Close"),
callback = function()
UIManager:close(viewer)
end,
}
if self.source == "terminal" then
buttons_table = {
{
back_button,
{
text = _("Back"),
text = _("Shortcuts"),
-- switch to shortcuts:
callback = function()
UIManager:close(viewer)
self:onTerminalStart()
self:manageShortcuts()
end,
},
close_button,
},
}
else
buttons_table = {
{
back_button,
{
text = _("Close"),
text = _("Terminal"),
-- switch to terminal:
callback = function()
UIManager:close(viewer)
self:terminal()
end,
},
close_button,
},
},
}
end
viewer = TextViewer:new{
title = _("Command output"),
text = table.concat(entries, "\n"),
justified = false,
text_face = Font:getFace("smallinfont"),
buttons_table = buttons_table,
}
UIManager:show(viewer)
end

Loading…
Cancel
Save