new object $has_commands: $foundation;
var $has_commands local = 0;
var $has_commands remote = 0;
var $has_commands shortcuts = #[];
var $root created_on = 796268969;
var $root fertile = 1;
var $root flags = ['methods, 'code, 'fertile, 'core, 'variables];
var $root inited = 1;
var $root managed = [$has_commands];
var $root manager = $has_commands;
public method .add_command() {
arg template, method, @type;
var cmd, types, count, x;
(> .perms(sender()) <);
[(type ?= 'local)] = type;
if ("*" in template)
throw(~invcmd, "Invalid command, command templates cannot contain \"*\"!.");
cmd = (> $command_lib.validate_command_template(template) <);
if (!(type in ['local, 'remote]))
throw(~type, "Command types can be either 'local or 'remote");
if ('this in (((cmd[2]).values()).slice(1)))
type = 'remote;
if (type == 'remote) {
for x in (((cmd[2]).values()).slice(1)) {
if (x == 'this)
count++;
}
if (!count)
throw(~add_command, "Command type defined as remote with no <this> argument.");
else if (count > 1)
throw(~add_command, "More than one <this> argument specified in template.");
}
if (!get_var(type))
set_var(type, #[]);
set_var(type, get_var(type).setadd_elem((cmd[1])[1], [@cmd[1], template, method, cmd[2]]));
};
public method .add_shortcut() {
arg shortcut, template, method;
var relation;
(> .perms(sender()) <);
if ((type(shortcut) != 'string) || (type(template) != 'string))
throw(~type, "Both shortcut and template must be strings.");
if (type(method) != 'symbol)
throw(~type, "Method must be submitted as a symbol.");
relation = (> $command_lib.parse_relation(shortcut, template) <);
shortcut = (relation[1])[1];
relation = (relation[2])[2];
if (!shortcuts)
shortcuts = #[];
shortcuts = shortcuts.add(shortcut, [method, relation]);
};
public method .all_local_commands() {
var cmds, a, acmds;
cmds = #[];
for a in (ancestors()) {
if (a == definer())
break;
if ((acmds = (| a.local_commands() |)))
cmds = cmds.add(a, acmds);
}
return cmds;
};
public method .all_remote_commands() {
var cmds, a, acmds;
cmds = #[];
for a in (ancestors()) {
if (a == definer())
break;
if ((acmds = (| a.remote_commands() |)))
cmds = cmds.add(a, acmds);
}
return cmds;
};
public method .all_shortcuts() {
var s, a, as;
s = [];
for a in (ancestors()) {
if (a == definer())
break;
if ((as = (| a.shortcuts() |)))
s += as.to_list();
}
return s;
};
public method .command_info() {
arg type, cmd;
return (| get_var(type)[cmd] |) || throw(~cmdnf, ("Command \"" + cmd) + "\" is not defined on this object.", cmd);
};
public method .del_command() {
arg template, method;
var cmd, c, d, info, type;
(> .perms(sender()) <);
cmd = template.explode();
if (!cmd)
throw(~type, "Invalid template.");
cmd = cmd[1];
info = #[['local, .get_command_info('local, cmd)]];
info = info.add('remote, .get_command_info('remote, cmd));
for type in (info) {
for c in (type[2]) {
if (((c[3]) == template) && ((c[4]) == method)) {
set_var(type[1], get_var(type[1]).del_elem(cmd, c));
d++;
}
}
}
return d;
};
public method .del_shortcut() {
arg shortcut;
var value;
(> .perms(sender()) <);
value = (| shortcuts.del(shortcut) |);
if (type(value) != 'dictionary)
throw(~shortcutnf, ("Shortcut \"" + shortcut) + "\" is not defined on this object.");
shortcuts = value;
};
public method .get_command_info() {
arg type, cmd;
var info, a, ainfo;
info = [];
for a in (ancestors()) {
if (a == definer())
break;
if ((ainfo = (| a.command_info(type, cmd) |)))
info = info.union(ainfo);
}
return info;
};
public method .get_shortcut_info() {
arg shortcut;
return (| shortcuts[shortcut] |) || throw(~shortcutnf, ("Shortcut \"" + shortcut) + "\" is not defined on this object.", shortcut);
};
root method .init_has_commands() {
local = (remote = (shortcuts = #[]));
};
public method .local_commands() {
return local || #[];
};
public method .remote_commands() {
return remote || #[];
};
public method .shortcuts() {
return shortcuts || #[];
};
root method .uninit_has_commands() {
.clear_variables(@.variables());
};