new object $editor_reference: $has_commands; var $editor_reference active_editor = 0; var $editor_reference bg_sessions = 0; var $has_commands local = \ #[["@mcp-upload-session", [["@mcp-upload-session", "*", "@mcp-upload-session <descendant of $editor_session>", 'mcp_upload_cmd, #[[1, ['descendant, [$editor_session]]]]]]],\ ["@cleanup-sessions|@c-s?essions",\ [["@cleanup-sessions|@c-s?essions", "", "@cleanup-sessions|@c-s?essions", 'cleanup_sessions, #[]]]], ["@edit", [["@edit", "*", "@edit <any>", 'edit_cmd, #[[1, ['any, []]]]]]]]; var $has_commands remote = #[]; var $has_commands shortcuts = #[]; var $root created_on = 820684615; var $root defined_settings = #[["local-editor", #[['parse, ['parse_local_editor]]]]]; var $root flags = ['methods, 'code, 'fertile, 'core, 'variables]; var $root inited = 1; var $root managed = [$editor_reference]; var $root manager = $editor_reference; var $root settings = #[["local-editor", 'none]]; public method .active_editor() { return active_editor; }; public method .background_editor_sessions() { return bg_sessions || []; }; public method .cleanup_sessions() { arg @who_cares; var out, s; (sender() == $housekeeper) || (> .perms(sender(), this()) <); out = []; for s in (bg_sessions || []) { if (valid(s) && (s.cleanup_session())) s.destroy(); else out = setadd(out, s); } bg_sessions = out; if (valid(active_editor) && (active_editor.cleanup_session())) { active_editor.destroy(); clear_var('active_editor); } return "Clean and invalid sessions cleared."; }; public method .do_save() { arg @info; // The purpose of this method is to ensure that save is ran with // this user's perms if ((!(sender().has_ancestor($editor_session))) || (!((sender().startup_sender()) == this()))) throw(~perm, "Permission denied"); return (> (info[1]).(info[2])(info[3], info[4]) <); }; protected method .edit() { arg ref, opts, type; if (.active_editor()) { .tell("Storing active editor.."); .store_editor(); } return .new_editor_session(ref, opts, type); }; public method .edit_cmd() { arg cmdstr, com, args; var syn, num, sess, out, type, i, e, bg; (> .perms(caller(), 'command) <); syn = "@edit <object reference> [+type=...]"; args = args.trim(); if (!args) { // list sessions out = []; e = .active_editor(); if (e) { if ($editor_parser in (.parsers())) out += ["** %0 " + (e.session_name())]; else out += [" %0 " + (e.session_name())]; } bg = .background_editor_sessions(); for sess in [1 .. listlen(bg)] out += [((" %" + sess) + " ") + ((bg[sess]).session_name())]; if (out) return ["Editor Sessions:"] + out; return "No editor sessions."; } else if ((args[1]) == "%") { // resume session args = substr(args, 2); if ((!args) || ((args[1]) == " ")) { num = 0; } else { catch ~nonum num = (> args.to_number() <); with return (traceback()[1])[2]; } if (!num) { if (.active_editor()) return .reinvoke_editor(.active_editor(), "%0"); else if (.background_editor_sessions()) sess = (.background_editor_sessions())[1]; else return "No sessions to resume."; } else { if ((listlen((.background_editor_sessions()) || []) < num) || (num < 0)) return ("There is not an editor session %" + num) + "."; sess = (.background_editor_sessions())[num]; } return .reinvoke_editor(sess, "%" + num); } else { args = $parse_lib.opt(args, "t?ype"); if ((i = "t?ype" in ((args[2]).slice(1)))) type = ((args[2])[i])[4]; type ?= "any"; catch ~objnf args = replace(args, 1, (> $parse_lib.ref((args[1]).join()) <)); with return (traceback()[1])[2]; return .edit(@args, type); } }; public method .edit_sessions_notify() { var e, s, bg; if (bg_sessions) { .tell("<editor> Use @edit to resume the following editor sessions:"); e = .active_editor(); if (e) { if ($editor_parser in (.parsers())) .tell("<editor> ** %0 " + (e.session_name())); else .tell("<editor> %0 " + (e.session_name())); } bg = .background_editor_sessions(); for s in [1 .. listlen(bg)] .tell((("<editor> %" + s) + " ") + ((bg[s]).session_name())); } else if (.active_editor()) { .tell("<editor> Disconnected from an active session. Use @edit %0 to resume."); } }; public method .invoke_editor() { arg @args; // finishing object, finishing method, initial text, client data; if (active_editor != 0) throw(~misc, "Editor already active"); active_editor = $editor_session.spawn(); if (active_editor.startup(@args)) .add_parser($editor_parser); }; public method .local_editor() { return .get_setting("local-editor", $editor_reference); }; protected method .mcp_upload_cmd() { arg cmdstr, cmd, session; var text, status, tmp; (> .perms(caller(), 'command) <); text = (| .read("Reading the editor session text...") |); if (type(text) != 'list) return "Upload failed."; if (!(session in bg_sessions)) return "Illegal session - upload failed."; tmp = active_editor; active_editor = session; catch any { status = session.mcp_upload(text); } with { .tell_traceback(traceback()); status = "Compilation failed."; } active_editor = tmp; return status[2]; }; public method .parse_local_editor() { arg value, @args; var styles; value = (| (styles = #[["None", 'none], ["MCP", 'mcp]])[value] |); if (!value) throw(~wrong, "Local editor must be one of: " + ((styles.keys()).to_english("", " or "))); return value; }; public method .quit_editor() { if (active_editor == 0) throw(~misc, "No active editor."); .perms(sender(), active_editor); .del_parser($editor_parser); active_editor.destroy(); clear_var('active_editor); }; protected method .reinvoke_editor() { arg @session; var i, t, name; t = ""; [(session ?= active_editor), (name ?= "")] = session; if (session == 0) return "No session to resume."; bg_sessions ?= []; if (active_editor && ((active_editor != session) || (!(| session.is_resumable() |)))) t = (.store_editor()) + " "; if ((!valid(session)) || (!(session in (bg_sessions + [active_editor])))) { active_editor = 0; return "Invalid session - editor cleared."; } if (!(| session.is_resumable() |)) return "The session is not resumable."; active_editor = session; bg_sessions = bg_sessions.setremove(active_editor); bg_sessions = filter i in (bg_sessions) where (valid(i)); .add_parser($editor_parser); return [t, ("Resumed editing " + ((.active_editor()).session_name())) + ".", "Type 'help' to list available commands."]; }; public method .store_editor() { var t; if (active_editor) { (sender() == this()) || (> .perms(sender(), active_editor) <); .del_parser($editor_parser); bg_sessions = (bg_sessions ? bg_sessions : []).setadd(active_editor); t = active_editor; active_editor = 0; return "Editor session %s saved.".format(t); } return "No active editor."; };