1 require("special-buffer.js");
2 require("interactive.js");
4 function help_buffer(window, element) {
6 conkeror.buffer.call(this, window, element, forward_keywords(arguments));
9 help_buffer.prototype = {
10 constructor: help_buffer,
12 __proto__: special_buffer.prototype
15 function where_is_command(buffer, command) {
16 var list = find_command_in_keymap(buffer, command);
19 msg = command + " is not on any key";
21 msg = command + " is on " + list.join(", ");
22 buffer.window.minibuffer.message(msg);
24 interactive("where-is", function (I) {
25 where_is_command(I.buffer,
26 (yield I.minibuffer.read_command($prompt = "Where is command:")));
29 function help_document_generator(document) {
30 dom_generator.call(this, document, XHTML_NS);
32 help_document_generator.prototype = {
33 __proto__: dom_generator.prototype,
35 key_binding : function(str, parent) {
36 var node = this.element("span", "class", "key-binding");
39 parent.appendChild(node);
43 source_code_reference : function(ref, parent) {
44 var f = this.document.createDocumentFragment();
45 var module_name = ref.module_name;
46 //f.appendChild(this.text(module_name != null ? "module " : "file "));
47 var x = this.element("a",
48 "class", "source-code-reference",
49 "href", "javascript:");
50 x.addEventListener("click", function (event) {
51 co_call(ref.open_in_editor());
52 event.preventDefault();
53 event.stopPropagation();
54 }, false /* capture */, false /* allow untrusted */);
55 x.textContent = (module_name != null ? module_name : ref.file_name);
58 parent.appendChild(f);
62 command_name : function(name, parent) {
63 var node = this.element("span", "class", "command");
64 this.text(name, node);
66 parent.appendChild(node);
70 command_reference : function(name, parent) {
71 var node = this.element("a", "class", "command", "href", "#");
72 /* FIXME: make this work */
73 this.text(name, node);
75 parent.appendChild(node);
79 variable_reference : function(name, parent) {
80 var node = this.element("a", "class", "variable", "href", "#");
81 /* FIXME: make this work */
82 this.text(name, node);
84 parent.appendChild(node);
88 help_text : function(str, parent) {
89 var paras = str.split("\n");
90 var f = this.document.createDocumentFragment();
91 for (var i = 0; i < paras.length; ++i) {
96 var p = this.element("p", f);
98 var regexp = /`([a-zA-Z0-9_\-$]+)\'/g;
102 while ((match = regexp.exec(para)) != null) {
103 this.text(para.substring(last_index, match.index), p);
104 var command = match[1];
105 /* FIXME: check if it is a valid command */
106 this.command_reference(command, p);
107 last_index = regexp.lastIndex;
109 if (last_index < para.length)
110 this.text(para.substring(last_index), p);
113 parent.appendChild(f);
117 add_help_stylesheet : function () {
118 this.add_stylesheet("chrome://conkeror/content/help.css");
122 define_keywords("$binding_list");
123 function describe_bindings_buffer(window, element) {
124 this.constructor_begin();
126 special_buffer.call(this, window, element, forward_keywords(arguments));
127 this.binding_list = arguments.$binding_list;
128 this.constructor_end();
131 describe_bindings_buffer.prototype = {
134 return help_buffer_keymap;
137 title : "Key bindings",
139 description : "*bindings*",
141 generate : function () {
142 var d = this.top_document;
143 var list = this.binding_list;
144 delete this.binding_list;
146 var g = new help_document_generator(d);
147 g.add_help_stylesheet();
149 d.body.setAttribute("class", "describe-bindings");
151 var table = d.createElementNS(XHTML_NS, "table");
152 for (var i = 0; i < list.length; ++i) {
154 var tr = d.createElementNS(XHTML_NS, "tr");
155 tr.setAttribute("class", (i % 2 == 0) ? "even" : "odd");
156 var seq_td = d.createElementNS(XHTML_NS, "td");
157 seq_td.setAttribute("class", "key-binding");
158 seq_td.textContent = bind.seq;
159 tr.appendChild(seq_td);
160 var command_td = d.createElementNS(XHTML_NS,"td");
161 command_td.setAttribute("class", "command");
163 if (bind.command != null) {
164 command_td.textContent = bind.command;
165 var cmd = interactive_commands.get(bind.command);
167 help_str = cmd.shortdoc;
169 else if (bind.fallthrough)
170 command_td.textContent = "[pass through]";
171 tr.appendChild(command_td);
172 var help_td = d.createElementNS(XHTML_NS, "td");
173 help_td.setAttribute("class", "help");
174 help_td.textContent = help_str || "";
175 tr.appendChild(help_td);
176 table.appendChild(tr);
178 d.body.appendChild(table);
181 __proto__: special_buffer.prototype
185 function describe_bindings(buffer, target) {
187 for_each_key_binding(buffer, function (binding_stack) {
188 var last = binding_stack[binding_stack.length - 1];
189 if (last.command == null && !last.fallthrough)
191 var bind = {seq: format_binding_sequence(binding_stack),
192 fallthrough: last.fallthrough,
193 command: last.command};
196 create_buffer(buffer.window, buffer_creator(describe_bindings_buffer,
197 $configuration = buffer.configuration,
198 $binding_list = list),
201 interactive("describe-bindings", function (I) {describe_bindings(I.buffer, I.browse_target("describe-bindings"));});
202 default_browse_targets["describe-bindings"] = "find-url";
206 define_keywords("$command", "$bindings");
207 function describe_command_buffer(window, element) {
208 this.constructor_begin();
210 special_buffer.call(this, window, element, forward_keywords(arguments));
211 this.bindings = arguments.$bindings;
212 this.command = arguments.$command;
213 this.cmd = interactive_commands.get(this.command);
214 this.source_code_reference = this.cmd.source_code_reference;
215 this.constructor_end();
218 describe_command_buffer.prototype = {
221 return help_buffer_keymap;
224 get title() { return "Command help: " + this.command; },
226 description : "*help*",
228 generate : function () {
229 var d = this.top_document;
231 var g = new help_document_generator(d);
233 g.add_help_stylesheet();
234 d.body.setAttribute("class", "describe-command");
238 p = g.element("p", d.body);
239 g.command_reference(this.command, p);
240 var cmd = interactive_commands.get(this.command);
241 if (cmd.source_code_reference) {
242 g.text(" is an interactive command in ", p);
243 g.source_code_reference(cmd.source_code_reference, p);
246 g.text(" is an interactive command.", p);
249 if (this.bindings.length > 0) {
250 p = g.element("p", d.body);
251 g.text("It is bound to ", p);
252 for (var i = 0; i < this.bindings.length; ++i) {
255 g.key_binding(this.bindings[i], p);
261 g.help_text(cmd.doc, d.body);
264 __proto__: special_buffer.prototype
268 function describe_command(buffer, command, target) {
269 var bindings = find_command_in_keymap(buffer, command);
270 create_buffer(buffer.window,
271 buffer_creator(describe_command_buffer,
272 $configuration = buffer.configuration,
274 $bindings = bindings),
277 interactive("describe-command", function (I) {
278 describe_command(I.buffer, (yield I.minibuffer.read_command($prompt = "Describe command:")),
279 I.browse_target("describe-command"));
281 default_browse_targets["describe-command"] = "find-url";
288 function view_referenced_source_code(buffer) {
289 if (buffer.source_code_reference == null)
290 throw interactive_error("Command not valid in current buffer.");
291 yield buffer.source_code_reference.open_in_editor();
293 interactive("view-referenced-source-code", function (I) {yield view_referenced_source_code(I.buffer);});
296 define_keywords("$binding", "$other_bindings", "$key_sequence");
297 function describe_key_buffer(window, element) {
298 this.constructor_begin();
300 special_buffer.call(this, window, element, forward_keywords(arguments));
301 this.key_sequence = arguments.$key_sequence;
302 this.bindings = arguments.$other_bindings;
303 this.bind = arguments.$binding;
304 this.source_code_reference = this.bind.source_code_reference;
305 this.constructor_end();
308 describe_key_buffer.prototype = {
311 return help_buffer_keymap;
314 get title() { return "Key help: " + this.key_sequence; },
316 description : "*help*",
318 generate : function () {
319 var d = this.top_document;
321 var g = new help_document_generator(d);
323 g.add_help_stylesheet();
324 d.body.setAttribute("class", "describe-key");
328 p = g.element("p", d.body);
329 g.key_binding(this.key_sequence, p);
330 g.text(" is bound to the command ", p);
331 var command = this.bind.command;
333 g.command_name("[pass through]", p);
335 g.command_reference(command, p);
336 if (this.source_code_reference) {
338 g.source_code_reference(this.source_code_reference, p);
342 if (command != null) {
343 p = g.element("p", d.body);
344 g.command_reference(command, p);
345 var cmd = interactive_commands.get(command);
346 if (cmd.source_code_reference) {
347 g.text(" is an interactive command in ", p);
348 g.source_code_reference(cmd.source_code_reference, p);
351 g.text(" is an interactive command.", p);
354 if (this.bindings.length > 0) {
355 p = g.element("p", d.body);
356 g.text("It is bound to ", p);
357 for (var i = 0; i < this.bindings.length; ++i) {
360 g.key_binding(this.bindings[i], p);
366 g.help_text(cmd.doc, d.body);
370 __proto__: special_buffer.prototype
374 function describe_key(buffer, key_info, target) {
376 var seq = key_info[0];
377 var bind = key_info[1];
380 bindings = find_command_in_keymap(buffer, bind.command);
384 create_buffer(buffer.window,
385 buffer_creator(describe_key_buffer,
386 $configuration = buffer.configuration,
387 $key_sequence = seq.join(" "),
388 $other_bindings = bindings,
392 interactive("describe-key", function (I) {
393 describe_key(I.buffer,
394 (yield I.minibuffer.read_key_binding($prompt = "Describe key:", $buffer = I.buffer)),
395 I.browse_target("describe-key"));
397 default_browse_targets["describe-key"] = "find-url";
402 define_keywords("$variable");
403 function describe_variable_buffer(window, element) {
404 this.constructor_begin();
406 special_buffer.call(this, window, element, forward_keywords(arguments));
407 this.bindings = arguments.$bindings;
408 this.variable = arguments.$variable;
409 this.cmd = interactive_variables.get(this.variable);
410 this.source_code_reference = this.cmd.source_code_reference;
411 this.constructor_end();
414 function pretty_print_value(value) {
415 if (value === undefined)
419 if (typeof(value) == "object")
420 return value.toSource();
421 if (typeof(value) == "function")
422 return value.toString();
423 if (typeof(value) == "string") {
424 let s = value.toSource();
425 // toSource returns: (new String("<blah>"))
426 // we want just: "<blah>"
427 return s.substring(12, s.length - 2);
429 return new String(value);
432 describe_variable_buffer.prototype = {
435 return help_buffer_keymap;
438 get title() { return "Variable help: " + this.variable; },
440 description : "*help*",
442 generate : function () {
443 var d = this.top_document;
445 var g = new help_document_generator(d);
447 g.add_help_stylesheet();
448 d.body.setAttribute("class", "describe-variable");
452 p = g.element("p", d.body);
453 g.variable_reference(this.variable, p);
454 var uvar = user_variables.get(this.variable);
455 if (uvar.source_code_reference) {
456 g.text(" is a user variable in ", p);
457 g.source_code_reference(uvar.source_code_reference, p);
460 g.text(" is a user variable.", p);
463 p = g.element("p", d.body);
464 g.text("It's value is: ", p);
466 let s = pretty_print_value(conkeror[this.variable]);
467 let pre = g.element("pre", p);
471 if (uvar.doc != null)
472 g.help_text(uvar.doc, d.body);
474 p = g.element("p", d.body);
475 g.text("It's default value is: ", p);
477 let s = pretty_print_value(user_variables.get(this.variable).default_value);
478 let pre = g.element("pre", p);
483 __proto__: special_buffer.prototype
487 function describe_variable(buffer, variable, target) {
488 create_buffer(buffer.window,
489 buffer_creator(describe_variable_buffer,
490 $configuration = buffer.configuration,
491 $variable = variable),
494 interactive("describe-variable", function (I) {
495 describe_variable(I.buffer, (yield I.minibuffer.read_user_variable($prompt = "Describe variable:")),
496 I.browse_target("describe-variable"));
498 default_browse_targets["describe-variable"] = "find-url";