parent $help_root
parent $user_interfaces
object $help_ui
var $root dbref 'help_ui
var $root child_index 0
var $root fertile 1
var $root manager $help_ui
var $root owned [$help_ui]
var $root owners [$help_ui]
var $root writable []
var $root readable ['parameters, 'methods, 'code]
var $root inited 1
var $help_ui current_node 0
var $help_ui help_evaluator 0
var $help_ui help_path 0
var $has_commands commands [["@help *", 'help_cmd], ["@help-link *", 'help_link_cmd]]
var $has_commands shortcuts [["?*", 'help_link_cmd, ["@help-link", 1]]]
var $old_command_environment verb_cache #[]
var $old_command_environment command_cache [["@help *", 'help_cmd], ["@help-link *", 'help_link_cmd]]
var $old_command_environment shortcuts_cache [["?*", 'help_link_cmd, ["@help-link", 1]]]
var $help_ui last_visited []
var $has_messages message_info #[]
var $has_messages messages 0
method help_link_cmd
arg cmd, what;
var way, p, node;
(> .perms(sender(), 'this) <);
catch ~nodenf {
if (!what) {
// stick with the current node
} else if (((what[1]) == "<") || ((what[1]) == ">")) {
(> ._navigate_node_history(what) <);
} else if ((what[1]) == "?") {
return ._help_node_history();
} else {
(> ._navigate_node(what) <);
}
} with handler {
.tell((traceback()[1])[2]);
return;
}
.build_help_page();
.
method init_help_ui
(> .perms(caller(), $root) <);
current_node = $help.default_help_node();
last_visited = #[['pos, 1], ['nodes, [current_node]]];
.
method current_node
return current_node;
.
method add_link
.perms(sender(), 'manager);
.
method help_cmd
arg cmd, args;
var cnode, n, nodes;
(> .perms(sender(), 'this) <);
args = args.explode();
if (args) {
cnode = (| ._find_help_node(args[1], 'index) |);
if (!cnode)
return;
for n in [2 .. listlen(args)] {
cnode = (| ._find_help_node(args[n], 'downnodes) |);
if (!cnode)
return;
}
} else {
cnode = $help.default_help_node();
}
.set_help_node(cnode, 'new);
.build_help_page();
.
method build_node_data
arg node;
var vars, message;
vars = $root_evaluator.fix_values(#[["downnodes", node.downnodes()], ["upnodes", node.upnodes()], ["title", node.title()]]);
vars = dict_add(vars, "body", (node.body()).ctext());
message = .eval_message("help.format", vars);
return message;
.
method eval_body
return body.eval_cml(#[['evaluator, $help_evaluator], ['time, 'pre]]);
.
method build_help_page
var out, len, clen, line, n;
(> .perms(sender(), 'this) <);
n = current_node;
len = ((.linelen()) % 2) ? (.linelen()) - 1 | (.linelen());
.tell(((" " + (n.name())) + " ").center(len, "-"));
.tell((n.body()).eval_ctext());
.tell(pad("", len, "-"));
if (n.upnodes())
.tell("Up-nodes: " + (((n.upnodes()).map('name)).to_english()));
if (n.downnodes())
.tell("Down-nodes: " + (((n.downnodes()).map('name)).to_english()));
.
method _find_help_node
arg what, type;
var pos, cnode;
(> .perms(sender(), 'this) <);
switch (type) {
case 'index:
cnode = $help_index.find_help_node(what);
if (cnode)
return cnode;
else
throw(~nodenf, ("Unable to find help on \"" + what) + "\".");
case 'link:
if (what in dict_keys(current_node.links()))
return (current_node.links())[what];
else
throw(~nodenf, ("No node link \"" + what) + "\" found on current node.");
default:
if (current_node.(type)()) {
if (strlen(what) == 1) {
return current_node.(type)()[1];
} else {
what = substr(what, 2);
pos = what in (current_node.(type)().map('name));
if (pos)
return current_node.(type)()[pos];
else
throw(~nodenf, "No downnode named " + what);
}
} else {
throw(~nodenf, ((("No " + tostr(type)) + " defined from node ") + (current_node.name())) + ".");
}
}
.
method _back_help_node
var p;
(> .perms(sender(), 'this) <);
p = (last_visited['pos]) - 1;
if (p) {
last_visited.add('pos, p);
return (last_visited['nodes])[p];
} else {
.tell("There are no more help nodes to step back to, in your history.");
throw(~stop, "", 'no_traceback);
}
.
method _forward_help_node
var p;
(> .perms(sender(), 'this) <);
p = (last_visited['pos]) + 1;
if (p <= listlen(last_visited['nodes])) {
last_visited.add('pos, p);
return (last_visited['nodes])[p];
} else {
.tell("There are no more help nodes to step forward to, in your history.");
throw(~stop, "", 'no_traceback);
}
.
method set_help_node
arg node, type;
var h, p, ns;
// god this is getting UGLY, but I can't think right now (sigh)
(> .perms(sender(), 'this) <);
current_node = node;
ns = last_visited['nodes];
p = last_visited['pos];
switch (type) {
case 'back, 'forward:
case 'new:
// hardcode the history cap for now
if (listlen(ns) >= 10)
ns = delete(h, 1);
ns = ns.union([node]);
last_visited = last_visited.add('nodes, ns);
}
last_visited = last_visited.add('pos, node in ns);
.
method _navigate_node_history
arg what;
var way, p;
(> .perms(sender(), 'this) <);
way = ((what[1]) == "<") ? 'back | 'forward;
if (strlen(what) == 1) {
.set_help_node(.(tosym(("_" + tostr(way)) + "_help_node"))(), way);
} else {
what = substr(what, 2);
p = what in ((last_visited['nodes]).map('name));
if (p)
.set_help_node((last_visited['nodes])[p], way);
else
throw(~nodenf, ("There is no node \"" + what) + "\" in your history.");
}
.
method _help_node_history
var n, ns, p, l;
(> .perms(sender(), 'this) <);
ns = last_visited['nodes];
p = last_visited['pos];
.tell("Help node history:");
for n in [1 .. listlen(ns)] {
if (p == n)
l = "=> ";
else
l = " ";
.tell(((l + pad(tostr(n) + ":", -2)) + " ") + ((ns[n]).name()));
}
.tell("--");
.
method _navigate_node
arg what;
var n, ns, p;
(> .perms(sender(), 'this) <);
catch ~nodenf {
n = ._find_help_node(what, 'link);
} with handler {
ns = (current_node.upnodes()) + (current_node.downnodes());
if (!ns)
rethrow(error());
p = what in (ns.map('name));
if (!p)
throw(~nodenf, ("No node found by the name \"" + what) + "\".");
n = ns[p];
}
.set_help_node(n, 'new);
.