2 * (C) Copyright 2007-2008 John J. Foerch
3 * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
5 * Use, modification, and distribution are subject to the terms specified in the
11 var interactive_commands = new string_hashmap();
14 * name: string name of the command.
16 * doc: Documentation string, may be null.
18 * handler: A function to handle the command.
20 * The $prefix keyword, when true, means that the command
21 * is a prefix-command.
23 define_keywords("$prefix", "$browser_object", "$prompt");
24 function interactive (name, doc, handler) {
29 browser_object: arguments.$browser_object,
30 prefix: arguments.$prefix,
32 shortdoc: get_shortdoc_string(doc),
33 prompt: arguments.$prompt,
34 source_code_reference: get_caller_source_code_reference() };
36 interactive_commands.put(name, cmd);
40 function interactive_error (str) {
41 var e = new Error(str);
42 e.__proto__ = interactive_error.prototype;
45 interactive_error.prototype.__proto__ = Error.prototype;
48 function interactive_context (buffer) {
49 this.local = conkeror;
52 this.window = this.buffer.window;
54 this.local = buffer.page.local;
56 this.local = buffer.local;
60 interactive_context.prototype = {
62 get P () this.prefix_argument,
64 get p () univ_arg_to_number(this.prefix_argument),
66 set p (default_value) univ_arg_to_number(this.prefix_argument, default_value),
68 get minibuffer () this.window.minibuffer,
72 function handle_interactive_error (window, e) {
75 if (e instanceof interactive_error) {
76 window.minibuffer.message(e.message);
77 } else if (e instanceof abort) {
78 window.minibuffer.message("Quit");
81 window.minibuffer.message("call interactively: " + e);
85 function call_interactively (I, command) {
88 var window = I.window;
90 if (typeof(command) == "function") {
91 // Special interactive command
96 var cmd = interactive_commands.get(command);
98 handle_interactive_error(
100 interactive_error("Invalid command: " + command));
107 // if there was no interactive browser-object,
108 // binding_browser_object becomes the default.
109 if (I.browser_object == null) {
110 I.browser_object = I.binding_browser_object;
112 // if the command's default browser object is a non-null literal,
113 // it overrides an interactive browser-object, but not a binding
115 if (cmd.browser_object != null &&
116 (! (cmd.browser_object instanceof browser_object_class)) &&
117 (I.binding_browser_object == null))
119 I.browser_object = cmd.browser_object;
121 // if we still have no browser-object, look for a page-mode
122 // default, or finally the command default.
123 if (I.browser_object == null) {
125 (I.buffer && I.buffer.default_browser_object_classes[command]) ||
129 handler = cmd.handler;
132 while (typeof(handler) == "string") {
133 let parent = interactive_commands.get(handler);
134 handler = parent.handler;
135 if (handler == command) {
136 throw (interactive_error("circular command alias, "+command));
140 var result = handler(I);
141 if (is_coroutine(result)) {
146 handle_interactive_error(window, e);
151 handle_interactive_error(window, e);
156 function alternates () {
157 let alts = Array.prototype.slice.call(arguments, 0);
158 return function (I) {
160 if (I.prefix_argument instanceof Array) {
161 let num = I.prefix_argument = I.prefix_argument[0];
162 while (num >= 4 && index + 1 < alts.length) {
167 yield alts[index](I);
173 * Utility functions for use in the rc to alter the behavior
174 * of interactive commands.
176 function set_handler (name, handler) {
177 var cmd = interactive_commands.get(name);
178 cmd.handler = handler;
181 function set_default_browser_object (name, browser_object) {
182 var cmd = interactive_commands.get(name);
183 cmd.browser_object = browser_object;