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