local SUPPORTED_KEYS = { { on = "0" }, { on = "1" }, { on = "2" }, { on = "3" }, { on = "4" }, { on = "5" }, { on = "6" }, { on = "7" }, { on = "8" }, { on = "9" }, { on = "A" }, { on = "B" }, { on = "C" }, { on = "D" }, { on = "E" }, { on = "F" }, { on = "G" }, { on = "H" }, { on = "I" }, { on = "J" }, { on = "K" }, { on = "L" }, { on = "M" }, { on = "N" }, { on = "O" }, { on = "P" }, { on = "Q" }, { on = "R" }, { on = "S" }, { on = "T" }, { on = "U" }, { on = "V" }, { on = "W" }, { on = "X" }, { on = "Y" }, { on = "Z" }, { on = "a" }, { on = "b" }, { on = "c" }, { on = "d" }, { on = "e" }, { on = "f" }, { on = "g" }, { on = "h" }, { on = "i" }, { on = "j" }, { on = "k" }, { on = "l" }, { on = "m" }, { on = "n" }, { on = "o" }, { on = "p" }, { on = "q" }, { on = "r" }, { on = "s" }, { on = "t" }, { on = "u" }, { on = "v" }, { on = "w" }, { on = "x" }, { on = "y" }, { on = "z" }, } local _notify = ya.sync(function(state, message) ya.notify({ title = state.notify.title, content = message, timeout = state.notify.timeout, level = state.notify.level, }) end) local _get_default_projects = ya.sync(function(state) return { list = {}, last = nil, } end) local _save_state = ya.sync(function(state, projects) state.projects = projects ps.pub_static(10, "projects", projects) end) local _load_state = ya.sync(function(state) ps.sub_remote("projects", function(body) if not state.projects and body then state.projects = _get_default_projects() for _, value in pairs(body.list) do state.projects.list[#state.projects.list + 1] = value end state.projects.last = body.last end end) end) local _get_projects = ya.sync(function(state) return not state.projects and _get_default_projects() or state.projects end) local _get_real_idx = ya.sync(function(state, idx) for real_idx, value in pairs(_get_projects().list) do if value.on == SUPPORTED_KEYS[idx].on then return tonumber(real_idx) end end return nil end) local _get_current_project = ya.sync(function(state) local tabs = cx.tabs -- TODO: add more tab properties local project = { active_idx = tonumber(tabs.idx), tabs = {}, } for index, tab in ipairs(tabs) do project.tabs[#project.tabs + 1] = { idx = index, cwd = tostring(tab.current.cwd), } end return project end) local save_project = ya.sync(function(state, idx, desc) local projects = _get_projects() local real_idx = _get_real_idx(idx) if not real_idx then real_idx = #projects.list + 1 end local project = _get_current_project() projects.list[real_idx] = { on = SUPPORTED_KEYS[idx].on, desc = desc, project = project, } if state.last.update_after_save then projects.last = project end _save_state(projects) if state.notify.enable then local message = string.format("Project saved to %s", state.projects.list[real_idx].on) _notify(message) end end) local load_project = ya.sync(function(state, project, desc) -- TODO: add more tab properties to restore for _ = 1, #cx.tabs - 1 do ya.manager_emit("tab_close", { 0 }) end local sorted_tabs = {} for _, tab in pairs(project.tabs) do sorted_tabs[tonumber(tab.idx)] = tab end for _, tab in pairs(sorted_tabs) do ya.manager_emit("tab_create", { tab.cwd }) end ya.manager_emit("tab_close", { 0 }) ya.manager_emit("tab_switch", { project.active_idx - 1 }) if state.last.update_after_load then local projects = _get_projects() projects.last = project _save_state(projects) end if state.notify.enable then local message if desc then message = string.format([["%s" loaded]], desc) else message = string.format([[Last project loaded]], desc) end _notify(message) end end) local delete_all_projects = ya.sync(function(state) _save_state(nil) if state.notify.enable then local message = "All projects deleted" _notify(message) end end) local delete_project = ya.sync(function(state, idx) local projects = _get_projects() local message = string.format([["%s" deleted]], tostring(projects.list[idx].desc)) table.remove(projects.list, idx) _save_state(projects) if state.notify.enable then _notify(message) end end) local save_last_and_quit = ya.sync(function(state) local projects = _get_projects() projects.last = _get_current_project() _save_state(projects) ya.manager_emit("quit", {}) end) return { entry = function(_, args) local action = args[1] if not action then return end if action == "save" then local idx = ya.which({ cands = SUPPORTED_KEYS, silent = false }) if not idx then return end local default_desc = string.format("Project %s", SUPPORTED_KEYS[idx].on) local value, event = ya.input({ title = "Project name:", value = default_desc, position = { "center", w = 40 }, }) if event ~= 1 then return end local desc if value ~= "" then desc = value else desc = default_desc end save_project(idx, desc) return end if action == "delete_all" then delete_all_projects() return end if action == "quit" then save_last_and_quit() return end local projects = _get_projects() if action == "load_last" then local last_project = projects.last if last_project then load_project(last_project) end return end local list = projects.list local selected_idx = ya.which({ cands = list, silent = false }) if not selected_idx then return end if action == "load" then local selected = list[selected_idx] load_project(selected.project, selected.desc) elseif action == "delete" then delete_project(selected_idx) end end, setup = function(state, args) state.last = { update_after_save = true, update_after_load = true, } if type(args.last) == "table" then if type(args.last.update_after_save) == "boolean" then state.last.update_after_save = args.last.update_after_save end if type(args.last.update_after_load) == "boolean" then state.last.update_after_load = args.last.update_after_load end end state.notify = { enable = true, title = "Projects", timeout = 3, level = "info", } if type(args.notify) == "table" then if type(args.notify.enable) == "boolean" then state.notify.enable = args.notify.enable end if type(args.notify.title) == "string" then state.notify.title = args.notify.title end if type(args.notify.timeout) == "number" then state.notify.timeout = args.notify.timeout end if type(args.notify.level) == "string" then state.notify.level = args.notify.level end end _load_state() end, }