parent $old_command_environment
object $has_commands
var $has_commands commands []
var $has_commands shortcuts []
var $root child_index 2
var $root owners [$has_commands]
var $root fertile 0
var $root inited 1
var $root owned [$has_commands]
var $root manager $has_commands
var $root writable [$has_commands]
var $root readable ['parameters, 'methods, 'code]
var $ title "untitled"
var $ brief ""
var $ help_name ""
var $ text []
var $ footnotes []
var $ references #[]
var $ upnode $
var $ subnodes []
var $ menu 0
var $root dbref 'has_commands
method init_has_commands
if (caller() != $root)
throw(~perm, "Caller is not $root.");
commands = [];
shortcuts = [];
.
method uninit_has_commands
if (caller() != $root)
throw(~perm, "Caller is not $root.");
commands = 0;
shortcuts = 0;
.
method add_command
arg template, method;
if (!(.is_writable_by(sender())))
throw(~perm, "Sender is not an owner.");
if ((type(template) != 'string) || (type(method) != 'symbol))
throw(~type, "Template and method are not a string and symbol.");
commands = [@commands, [template, method]];
.
method del_command
arg match;
var command, x;
.perms(sender());
// so you can do both template or method
if (type(match) == 'symbol)
x = 2;
else if (type(match) == 'string)
x = 1;
else
throw(~type, "Type must either be a string or symbol (template or method).");
for command in (commands) {
if ((command[x]) == match) {
commands = setremove(commands, command);
return;
}
}
throw(~commandnf, "No command with match " + toliteral(match));
.
method add_shortcut
arg pattern, method, subs;
if (!(.is_writable_by(sender())))
throw(~perm, "Sender is not an owner.");
if ((type(pattern) != 'string) || ((type(method) != 'symbol) || (type(subs) != 'list)))
throw(~type, "Pattern, method, and subs are not a string, symbol, and list.");
shortcuts = [@shortcuts, [pattern, method, subs]];
.
method del_shortcut
arg method;
var shortcut;
if (!(.is_writable_by(sender())))
throw(~perm, "Sender is not an owner.");
for shortcut in (shortcuts) {
if ((shortcut[2]) == method) {
shortcuts = setremove(shortcuts, shortcut);
return;
}
}
throw(~shortcutnf, "No shortcut with method " + tostr(method));
.
method match_command
arg str;
var shortcut, cmd, fields, shortcuts, commands;
// Try shortcuts.
shortcuts = .xshortcuts_cache();
for shortcut in (shortcuts) {
fields = match_pattern(shortcut[1], str);
if (fields)
return [shortcut[2], .sub_shortcut_fields(shortcut[3], fields)];
}
// Try commands.
commands = .xcommand_cache();
for cmd in (commands) {
fields = match_template(cmd[1], str);
if (fields)
return [cmd[2], fields];
}
// Give up.
return 0;
.
method commands
return commands;
.
method all_commands
var p, cmdlist, pc;
// Collect complete command list from ancestors. Ancestors may not be
// command-handling objects, in which case (| p.commands() |) is
// ~methodnf.
cmdlist = [];
for p in (ancestors()) {
pc = (| p.commands() |);
if (pc)
cmdlist = cmdlist + pc;
if (p == definer())
break;
}
return cmdlist;
.
method shortcuts
return shortcuts;
.
method all_shortcuts
var ancestor, list, ancestor_shortcuts;
// Collect complete command list from ancestors. Ancestors may not be
// command-handling objects, in which case (| p.shortcuts() |) is
// ~methodnf.
list = [];
for ancestor in (ancestors()) {
ancestor_shortcuts = (| ancestor.shortcuts() |);
if (ancestor_shortcuts)
list = list + ancestor_shortcuts;
if (ancestor == definer())
break;
}
return list;
.
method sub_shortcut_fields
arg subs, fields;
var subbed_list, elem;
subbed_list = [];
for elem in (subs) {
if (type(elem) == 'string)
subbed_list = [@subbed_list, elem];
else if (type(elem) == 'integer)
subbed_list = [@subbed_list, (> fields[elem] <)];
else
throw(~type, "Substitution element is of wrong type.");
}
return subbed_list;
.
method command_info
arg t;
var x, y, out;
// eventually will change commands to use dictionaries.
out = [];
for x in (commands) {
y = ((x[1]).explode())[1];
if (match_template(y, t))
out = [@out, x];
}
return out;
.