You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
6.3 KiB
Lua
217 lines
6.3 KiB
Lua
----------------------------------------------------------------
|
|
-- Multi-Session save/restore Plugin --
|
|
----------------------------------------------------------------
|
|
|
|
local ipairs = ipairs
|
|
local tostring = tostring
|
|
local lfs = lfs
|
|
local os = os
|
|
local io = io
|
|
local table = table
|
|
local string = string
|
|
local unpack = unpack
|
|
local lousy = require "lousy"
|
|
local util = lousy.util
|
|
local luakit = luakit
|
|
local window = window
|
|
local add_binds, add_cmds = add_binds, add_cmds
|
|
local new_mode, menu_binds = new_mode, menu_binds
|
|
local cmd = lousy.bind.cmd
|
|
local buf = lousy.bind.buf
|
|
|
|
module("plugins.multisession")
|
|
|
|
local sessions_dir = luakit.data_dir .. "/sessions"
|
|
|
|
local rm = function (file)
|
|
luakit.spawn(string.format("rm %q", file))
|
|
end
|
|
|
|
local session_save = function (w, name)
|
|
if not name then return end
|
|
local fpath = sessions_dir .. "/" .. (name or "")
|
|
-- Save all given windows uris to file.
|
|
local lines = {}
|
|
-- Save tabs from all the given window, keep the window-index to keep
|
|
-- comptability with default sessions format
|
|
local current = w.tabs:current()
|
|
for ti, tab in ipairs(w.tabs.children) do
|
|
table.insert(lines, string.format("%d\t%d\t%s\t%s", 1, ti,
|
|
tostring(current == ti), tab.uri))
|
|
end
|
|
-- Only save a non-empty session
|
|
if #lines > 0 then
|
|
local fh = io.open(fpath, "w")
|
|
fh:write(table.concat(lines, "\n"))
|
|
io.close(fh)
|
|
else
|
|
rm(session.file)
|
|
end
|
|
end
|
|
|
|
local session_load = function (name)
|
|
local fpath = sessions_dir .. "/" .. (name or "")
|
|
if not name or not os.exists(fpath) then return end
|
|
local ret = {}
|
|
|
|
-- Read file
|
|
local lines = {}
|
|
local fh = io.open(fpath, "r")
|
|
for line in fh:lines() do table.insert(lines, line) end
|
|
io.close(fh)
|
|
|
|
-- Parse session file, again, ignore the window-index, keeping for
|
|
-- compatibility
|
|
for _, line in ipairs(lines) do
|
|
local wi, ti, current, uri = unpack(util.string.split(line, "\t"))
|
|
current = (current == "true")
|
|
table.insert(ret, {uri = uri, current = current})
|
|
end
|
|
|
|
return (#ret > 0 and ret) or nil
|
|
end
|
|
|
|
-- Create a new window and open all tabs in the session in it
|
|
local session_restore = function (name)
|
|
win = session_load(name)
|
|
if not win or #win == 0 then return end
|
|
|
|
-- Spawn windows
|
|
local w
|
|
for _, item in ipairs(win) do
|
|
if not w then
|
|
w = window.new({item.uri})
|
|
else
|
|
w:new_tab(item.uri, item.current)
|
|
end
|
|
end
|
|
return w
|
|
end
|
|
|
|
-- Opens all tabs in named session in current window
|
|
local session_append = function (w, name)
|
|
ses = session_load(name)
|
|
if not ses or #ses == 0 then return false end
|
|
for _, item in ipairs(ses) do
|
|
w:new_tab(item.uri, item.current)
|
|
end
|
|
return true
|
|
end
|
|
|
|
local session_del = function (name)
|
|
if not name then return end
|
|
local fpath = sessions_dir .. "/" .. (name or "")
|
|
if not os.exists(fpath) then return false end
|
|
rm(fpath)
|
|
return true
|
|
end
|
|
|
|
local load = function ()
|
|
local curdir = lfs.currentdir()
|
|
if not lfs.chdir(sessions_dir) then
|
|
lfs.mkdir(sessions_dir)
|
|
else
|
|
lfs.chdir(curdir)
|
|
end
|
|
end
|
|
|
|
add_cmds({
|
|
cmd("session", "view list of sessions", function (w) w:set_mode("sessionmenu") end),
|
|
cmd({"session-write", "sw"}, "save a session to file",
|
|
function (w, a)
|
|
local name = util.string.strip(a) or "default"
|
|
session_save(w, name)
|
|
w:notify("Saved " .. tostring(w.tabs:count()) .. " tabs to session " .. name .. ".")
|
|
end),
|
|
cmd({"session-delete", "sd"}, "delete a saved session",
|
|
function(w, a)
|
|
local name = util.string.strip(a)
|
|
if session_del(name) then
|
|
w:notify("Deleted session " .. name .. ".")
|
|
else
|
|
w:error("No saved session named " .. name .."!")
|
|
end
|
|
end),
|
|
cmd({"session-restore", "sr"}, "load a saved session in a new window",
|
|
function(w, a)
|
|
local name = util.string.strip(a) or "default"
|
|
if not session_restore(name) then
|
|
w:error("Unable to restore session " .. name .. "!")
|
|
end
|
|
end),
|
|
cmd({"session-open", "so"}, "open a saved session in new tabs in current window",
|
|
function(w, a)
|
|
local name = util.string.strip(a) or "default"
|
|
if not session_append(w, name) then
|
|
w:error("Unable to open session " .. name .. "!")
|
|
else
|
|
w:notify("Appended session " .. name .. " to tabs.")
|
|
end
|
|
end),
|
|
})
|
|
|
|
add_binds("normal", {
|
|
buf("^sm$", "open list of saved sessions", function(w) w:set_mode("sessionmenu") end),
|
|
})
|
|
|
|
|
|
|
|
new_mode("sessionmenu", {
|
|
enter = function (w)
|
|
local rows = {{"Saved Sessions (# of tabs)", title = true}}
|
|
|
|
for filename in lfs.dir(sessions_dir) do
|
|
if not string.match(filename, "^%.-$") then
|
|
local fh = io.open(sessions_dir .. "/" .. filename)
|
|
local tabcnt = 0
|
|
for _ in fh:lines() do tabcnt = tabcnt + 1 end
|
|
io.close(fh)
|
|
table.insert(rows, {string.format(" %s (%d)", filename, tabcnt), name = filename})
|
|
end
|
|
end
|
|
if #rows == 1 then
|
|
table.insert(rows, {"No saved sessions!"})
|
|
end
|
|
w.menu:build(rows)
|
|
w:notify("Use j/k to move, d to delete a session, t to append session to current window, Enter to open session (in new window)", false)
|
|
end,
|
|
|
|
leave = function (w)
|
|
w.menu:hide()
|
|
end,
|
|
})
|
|
|
|
local key = lousy.bind.key
|
|
add_binds("sessionmenu", lousy.util.table.join({
|
|
key({}, "Return", function (w)
|
|
local row = w.menu:get()
|
|
if row and row.name then
|
|
w:set_mode()
|
|
session_restore(row.name)
|
|
end
|
|
end),
|
|
|
|
key({}, "t", function (w)
|
|
local row = w.menu:get()
|
|
if row and row.name then
|
|
w:set_mode()
|
|
session_append(w, row.name)
|
|
end
|
|
end),
|
|
|
|
key({}, "d", function (w)
|
|
local row = w.menu:get()
|
|
if row and row.name then
|
|
w.menu:del()
|
|
session_del(row.name)
|
|
end
|
|
end),
|
|
|
|
-- Exit menu
|
|
key({}, "q", function (w) w:set_mode() end),
|
|
|
|
}, menu_binds))
|
|
|
|
load()
|
|
-- vim: et:sw=4:ts=8:sts=4:tw=80
|