parent user parent properties object help_user var root name 'help_user var help_user inited 1 var help_user current_help $help_root method init arg ancestors; pass(ancestors); if (definer() in ancestors) current_help = $help_root; . eval .initialize(); .add_property('help_dict, #[["*", $help_root], ["help", $help_help], ["**", $user_help]]); .set_vr_name("Clueless"); .add_command("help *", 'help_cmd); .add_shortcut("?*", 'help_cmd, ["help", 1]); . method help_dict return .get_property('help_dict); . method match_help_path arg string; var current, node; current = current_help; for node in (explode(string)) current = (> .match_help_node(node, current) <); return current; . method match_help_node arg string, current; var node, sib, i; switch (string) { case ">": node = current; while (1) { if (node == $help_root) throw(~keynf, current.name() + " has no successor."); sib = node.upnode().subnodes(); i = node in sib; if (i && i < listlen(sib)) return sib[i+1]; node = node.upnode(); } case "<": node = current; while (1) { if (node == $help_root) throw(~keynf, current.name() + " has no predecessor."); sib = node.upnode().subnodes(); i = node in sib; if (i > 1) return sib[i-1]; node = node.upnode(); } case "..": if (current == $help_root) throw(~keynf, "Top node has no supernode."); return current.upnode(); case "?": if (!current.subnodes()) return (> .match_help_node(">", current) <); return current.subnodes()[1]; } catch ~keynf { return .get_property('help_dict)[string]; } return (> current.match_menu(string) <); . method help_cmd arg string, [rest]; if (rest) string = rest[1]; else if (string == "help") string = ""; catch ~range { sender().tell("[:" + string + ":] " + current_help.footnote(toint(string))); return; } catch ~keynf { current_help = .match_help_path(string); } with handler { sender().tell("No help found on " + toliteral(string) + "."); return; } sender().tell(current_help.text()); if (current_help.subnodes()) sender().tell("-----[[ `??' to read " + current_help.subnodes()[1].brief() + " (" + current_help.subnodes()[1].name() + ") ]]"); else catch ~keynf { string = .match_help_node("?", current_help); sender().tell("-----[[ `??' to read " + string.brief() + " (" + $list.to_string($list.map(string.path(), 'name), " ") + " " + string.name() + ") ]]"); } with handler { sender().tell("-----[[ Last node. `?*' to return to the top. ]]"); } .