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.";
};