Factor out mime.js matching logic to predicate_alist_match
[conkeror.git] / modules / interactive.js
bloba55f31dfa972eedeae25f7dfa49a88e5f23370d7
1 require("utils.js");
3 var interactive_commands = new string_hashmap();
5 /**
6  * First argument is the command name.
7  *
8  * This is optionally followed by a documentation string.
9  *
10  * This is followed by the command function.
11  */
12 function interactive(name)
14     var doc = null;
15     var handler;
16     var offset = 1;
17     if (typeof(arguments[1]) == "string" || arguments[1] == null)
18     {
19         doc = arguments[1];
20         offset = 2;
21     }
22     handler = arguments[offset++];
23     var cmd = {
24         name: name,
25         handler: handler,
26         doc: doc,
27         shortdoc: get_shortdoc_string(doc),
28         source_code_reference: get_caller_source_code_reference() };
30     interactive_commands.put(name, cmd);
33 function interactive_error(str) {
34     var e = new Error(str);
35     e.__proto__ = interactive_error.prototype;
36     return e;
38 interactive_error.prototype.__proto__ = Error;
40 function interactive_context() {}
41 interactive_context.prototype = {
43     get P () this.prefix_argument,
45     get p () univ_arg_to_number(this.prefix_argument),
47     set p (default_value) univ_arg_to_number(this.prefix_argument, default_value),
49     get minibuffer () this.window.minibuffer
52 function handle_interactive_error(window, e) {
53     if (e instanceof interactive_error)
54         window.minibuffer.message(e.message);
55     else if (e instanceof abort)
56         window.minibuffer.message("Quit");
57     else {
58         dump_error(e);
59         window.minibuffer.message("call interactively: " + e);
60     }
63 // Any additional arguments specify "given" arguments to the function.
64 function call_interactively(I, command)
66     var handler;
67     var top_args;
69     I.__proto__ = interactive_context.prototype;
71     if (I.buffer == null)
72         I.buffer = I.window.buffers.current;
73     else if (I.window == null)
74         I.window = I.buffer.window;
76     var window = I.window;
78     if (typeof(command) == "function") {
79         // Special interactive command
80         command(I);
81         return;
82     }
84     var cmd = interactive_commands.get(command);
85     if (!cmd)
86     {
87         window.minibuffer.message("Invalid command: " + command);
88         return;
89     }
91     I.command = command;
93     var handler = cmd.handler;
94     
95     try {
96         var result = handler(I);
97         if (is_coroutine(result)) {
98             co_call(function() {
99                 try {
100                     yield result;
101                 } catch (e) {
102                     handle_interactive_error(window, e);
103                 }
104             }());
105         }
106     } catch (e)
107     {
108         handle_interactive_error(window, e);
109     }
113 I.f = interactive_method(
114     $doc = "Existing file",
115     $async = function (ctx, cont) {
116         keywords(arguments, $prompt = "File:", $initial_value = default_directory.path,
117                  $history = "file");
118         ctx.window.minibuffer.read(
119             $prompt = arguments.$prompt,
120             $initial_value = arguments.$initial_value,
121             $history = arguments.$history,
122             $callback = function(s) {
123                 var f = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
124                 f.initWithPath(s);
125                 cont(f);
126             });
127     });
129 // FIXME: eventually they will differ, when completion for files is added
130 I.F = I.f;