tab_bar.prototype.destroy delete window.tab_bar.
[conkeror.git] / modules / interactive.js
blob1e98ea105e347ab25ec6166107c76dc77d602475
1 /**
2  * (C) Copyright 2007-2009 John J. Foerch
3  * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
4  *
5  * Use, modification, and distribution are subject to the terms specified in the
6  * COPYING file.
7 **/
9 in_module(null);
11 require("utils.js");
13 var interactive_commands = new string_hashmap();
15 /**
16  * name: string name of the command.
17  *
18  * doc: Documentation string, may be null.
19  *
20  * handler: A function to handle the command.
21  *
22  * The $prefix keyword, when true, means that the command
23  * is a prefix-command.
24  */
25 define_keywords("$prefix", "$browser_object", "$prompt");
26 function interactive (name, doc, handler) {
27     keywords(arguments);
28     var cmd = {
29         name: name,
30         handler: handler,
31         browser_object: arguments.$browser_object,
32         prefix: arguments.$prefix,
33         doc: doc,
34         shortdoc: get_shortdoc_string(doc),
35         prompt: arguments.$prompt,
36         source_code_reference: get_caller_source_code_reference() };
38     interactive_commands.put(name, cmd);
39     return name;
42 function interactive_error (str) {
43     var e = new Error(str);
44     e.__proto__ = interactive_error.prototype;
45     return e;
47 interactive_error.prototype.__proto__ = Error.prototype;
50 function interactive_context (buffer) {
51     this.local = conkeror;
52     this.buffer = buffer;
53     if (buffer) {
54         this.window = this.buffer.window;
55         if (buffer.page) {
56             this.local = buffer.page.local;
57         } else {
58             this.local = buffer.local;
59         }
60     }
62 interactive_context.prototype = {
63     constructor: interactive_context,
65     get P () this.prefix_argument,
67     get p () univ_arg_to_number(this.prefix_argument),
69     set p (default_value) univ_arg_to_number(this.prefix_argument, default_value),
71     get minibuffer () this.window.minibuffer,
75 function handle_interactive_error (window, e) {
76     if (! window)
77         throw e;
78     if (e instanceof interactive_error) {
79         window.minibuffer.message(e.message);
80     } else if (e instanceof abort) {
81         window.minibuffer.message("Quit");
82     } else {
83         dump_error(e);
84         window.minibuffer.message("call interactively: " + e);
85     }
88 function call_interactively (I, command) {
89     var handler;
90     var window = I.window;
92     if (typeof command == "function") {
93         // Special interactive command
94         command(I);
95         yield co_return();
96     }
98     var cmd = interactive_commands.get(command);
99     if (!cmd) {
100         handle_interactive_error(
101             window,
102             interactive_error("Invalid command: " + command));
103         yield co_return();
104     }
106     I.command = cmd;
109     // if there was no interactive browser-object,
110     // binding_browser_object becomes the default.
111     if (I.browser_object === undefined) {
112         I.browser_object = I.binding_browser_object;
113     }
114     // if the command's default browser object is a non-null literal,
115     // it overrides an interactive browser-object, but not a binding
116     // browser object.
117     if (cmd.browser_object != null &&
118         (! (cmd.browser_object instanceof browser_object_class)) &&
119         (I.binding_browser_object === undefined))
120     {
121         I.browser_object = cmd.browser_object;
122     }
123     // if we still have no browser-object, look for a page-mode
124     // default, or finally the command default.
125     if (I.browser_object === undefined) {
126         I.browser_object =
127             (I.buffer && I.buffer.default_browser_object_classes[command]) ||
128             cmd.browser_object;
129     }
131     handler = cmd.handler;
133     try {
134         while (typeof handler == "string") {
135             let parent = interactive_commands.get(handler);
136             handler = parent.handler;
137             if (handler == command) {
138                 throw (interactive_error("circular command alias, "+command));
139             }
140         }
142         try {
143             yield handler(I);
144         } catch (e) {
145             handle_interactive_error(window, e);
146         }
147     } catch (e) {
148         handle_interactive_error(window, e);
149     }
153 function alternates () {
154     let alts = Array.prototype.slice.call(arguments, 0);
155     return function (I) {
156         var index = 0;
157         if (I.prefix_argument instanceof Array) {
158             let num = I.prefix_argument = I.prefix_argument[0];
159             while (num >= 4 && index + 1 < alts.length) {
160                 num = num / 4;
161                 index++;
162             }
163         }
164         yield alts[index](I);
165     };
170  * Utility functions for use in the rc to alter the behavior
171  * of interactive commands.
172  */
173 function set_handler (name, handler) {
174     var cmd = interactive_commands.get(name);
175     cmd.handler = handler;
178 function set_default_browser_object (name, browser_object) {
179     var cmd = interactive_commands.get(name);
180     cmd.browser_object = browser_object;
183 provide("interactive");