define_browser_object_class: changed arg `hint` to keyword `$hint`
[conkeror/arlinius.git] / modules / commands.js
blob1ff5ba1c8d5c5afcaa20733a8c11bcc8fbd28d80
1 /**
2  * (C) Copyright 2004-2007 Shawn Betts
3  * (C) Copyright 2007-2008 John J. Foerch
4  * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
5  *
6  * Use, modification, and distribution are subject to the terms specified in the
7  * COPYING file.
8 **/
10 require("content-buffer.js");
12 define_hook("quit_hook");
14 function quit () {
15     quit_hook.run();
16     var appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
17         .getService(Ci.nsIAppStartup);
18     appStartup.quit(appStartup.eAttemptQuit);
20 interactive("quit",
21             "Quit Conkeror",
22             quit);
24 interactive("confirm-quit",
25             "Quit Conkeror with confirmation",
26             function (I) {
27                 let result = yield I.window.minibuffer.read_single_character_option(
28                     $prompt = "Quit Conkeror? (y/n)",
29                     $options = ["y", "n"]);
30                 if (result == "y")
31                     quit();
32             });
34 function show_conkeror_version (window) {
35     window.minibuffer.message(conkeror.version);
37 interactive("conkeror-version",
38             "Show version information for Conkeror.",
39             function (I) { show_conkeror_version(I.window); });
40 interactive("version",
41             "Show version information for Conkeror.",
42             "conkeror-version");
44 /* FIXME: maybe this should be supported for non-browser buffers */
45 function scroll_horiz_complete (buffer, n) {
46     var w = buffer.focused_frame;
47     w.scrollTo (n > 0 ? w.scrollMaxX : 0, w.scrollY);
49 interactive("scroll-beginning-of-line",
50             "Scroll the current frame all the way to the left.",
51             function (I) { scroll_horiz_complete(I.buffer, -1); });
53 interactive("scroll-end-of-line",
54             "Scroll the current frame all the way to the right.",
55             function (I) { scroll_horiz_complete(I.buffer, 1); });
57 function delete_window (window) {
58     window.window.close();
60 interactive("delete-window",
61             "Delete the current window.",
62             function (I) { delete_window(I.window); });
64 interactive("jsconsole",
65             "Open the JavaScript console.",
66             "find-url-new-buffer",
67             $browser_object = "chrome://global/content/console.xul");
69 /**
70  * Given a callback func and an interactive context I, call func, passing either
71  * a focused field, or the minibuffer's input element if the minibuffer is
72  * active. Afterward, call `ensure_index_is_visible' on the field. See
73  * `paste_x_primary_selection' and `open_line' for examples.
74  */
75 function call_on_focused_field (I, func) {
76     var m = I.window.minibuffer;
77     var s = m.current_state;
78     if (m._input_mode_enabled) {
79         m._restore_normal_state();
80         var e = m.input_element;
81     } else
82         var e = I.buffer.focused_element;
83     func(e);
84     ensure_index_is_visible(I.window, e, e.selectionStart);
85     if (s && s.handle_input)
86         s.handle_input(m);
89 /**
90  * Replace the current region with modifier(selection). Deactivates region and
91  * sets point to the end of the inserted text, unless keep_point is true, in
92  * which case the point will be left at the beginning of the inserted text.
93  */
94 function modify_region (field, modifier, keep_point) {
95     var replacement =
96         modifier(field.value.substring(field.selectionStart, field.selectionEnd+1));
97     var point = field.selectionStart;
98     field.value =
99         field.value.substr(0, field.selectionStart) + replacement +
100         field.value.substr(field.selectionEnd);
101     if (!keep_point) point += replacement.length;
102     field.setSelectionRange(point, point);
105 function paste_x_primary_selection (field) {
106     modify_region(field, function (str) read_from_x_primary_selection());
108 interactive("paste-x-primary-selection",
109     "Insert the contents of the X primary selection into the selected field or "+
110     "minibuffer. Deactivates the region if it is active, and leaves the point "+
111     "after the inserted text.",
112     function (I) call_on_focused_field(I, paste_x_primary_selection));
114 function open_line (field) {
115     modify_region(field, function() "\n", true);
118 interactive("open-line",
119     "If there is an active region, replace is with a newline, otherwise just "+
120     "insert a newline. In both cases leave point before the inserted newline.",
121     function (I) call_on_focused_field(I, open_line));
123 function transpose_chars (field) {
124     var value = field.value;
125     var caret = field.selectionStart; // Caret position.
126     var length = value.length;
128     // If we have less than two character in the field or if we are at the
129     // beginning of the field, do nothing.
130     if (length <= 2 || caret == 0)
131         return;
133     // If we are at the end of the field, switch places on the two last
134     // characters. TODO: This should happen at the end of every line, not only
135     // at the end of the field.
136     if (caret == length)
137         caret--;
139     // Do the transposing.
140     field.value = switch_subarrays(value, caret - 1, caret, caret, caret + 1);
142     // Increment the caret position. If this is not done, the caret is left at
143     // the end of the field as a result of the replacing of contents.
144     field.selectionStart = caret + 1;
145     field.selectionEnd = caret + 1;
148 interactive("transpose-chars",
149     "Interchange characters around point, moving forward one character.",
150     function (I) call_on_focused_field(I, transpose_chars));
152 function meta_x (buffer, prefix, command, browser_object) {
153     var I = new interactive_context(buffer);
154     I.prefix_argument = prefix;
155     I.browser_object = browser_object;
156     call_interactively(I, command);
158 interactive("execute-extended-command",
159             "Execute a Conkeror command specified in the minibuffer.",
160             function (I) {
161                 var prefix = I.P;
162                 var boc = I.browser_object;
163                 var prompt = "";
164                 if (boc)
165                     prompt += ' ['+boc.name+']';
166                 if (prefix !== null && prefix !== undefined) {
167                     if (typeof prefix == "object")
168                         prompt += prefix[0] == 4 ? " C-u" : " "+prefix[0];
169                     else
170                         prompt += " "+prefix;
171                 }
172                 meta_x(I.buffer, I.P,
173                        (yield I.minibuffer.read_command(
174                            $prompt = "M-x" + prompt)),
175                        boc);
176             });
178 /// built in commands
179 // see: http://www.xulplanet.com/tutorials/xultu/commandupdate.html
181 // Performs a command on a browser buffer content area
184 define_builtin_commands(
185     "",
186     function (I, command) {
187         var buffer = I.buffer;
188         try {
189             buffer.do_command(command);
190         } catch (e) {
191             /* Ignore exceptions */
192         }
193     },
194     function (I) {
195         I.buffer.mark_active = !I.buffer.mark_active;
196     },
197     function (I) I.buffer.mark_active,
198     false
201 define_builtin_commands(
202     "caret-",
203     function (I, command) {
204         var buffer = I.buffer;
205         try {
206             buffer.do_command(command);
207         } catch (e) {
208             /* Ignore exceptions */
209         }
210     },
211     function (I) {
212         I.buffer.mark_active = !I.buffer.mark_active;
213     },
214     function (I) I.buffer.mark_active,
215     'caret');
217 function get_link_text () {
218     var e = document.commandDispatcher.focusedElement;
219     if (e && e.getAttribute("href")) {
220         return e.getAttribute("href");
221     }
222     return null;
227 function copy_email_address (loc)
229     // Copy the comma-separated list of email addresses only.
230     // There are other ways of embedding email addresses in a mailto:
231     // link, but such complex parsing is beyond us.
232     var qmark = loc.indexOf( "?" );
233     var addresses;
235     if ( qmark > 7 ) {                   // 7 == length of "mailto:"
236         addresses = loc.substring( 7, qmark );
237     } else {
238         addresses = loc.substr( 7 );
239     }
241     //XXX: the original code, which we got from firefox, unescapes the string
242     //     using the current character set.  To do this in conkeror, we
243     //     *should* use an interactive method that gives us the character set,
244     //     rather than fetching it by side-effect.
246     //     // Let's try to unescape it using a character set
247     //     // in case the address is not ASCII.
248     //     try {
249     //         var characterSet = this.target.ownerDocument.characterSet;
250     //         const textToSubURI = Components.classes["@mozilla.org/intl/texttosuburi;1"]
251     //             .getService(Components.interfaces.nsITextToSubURI);
252     //         addresses = textToSubURI.unEscapeURIForUI(characterSet, addresses);
253     //     }
254     //     catch(ex) {
255     //         // Do nothing.
256     //     }
258     writeToClipboard(addresses);
259     message("Copied '" + addresses + "'");
261 interactive("copy-email-address", copy_email_address, ['focused_link_url']);
264 /* FIXME: fix this command */
266 interactive("source",
267             "Load a JavaScript file.",
268             function (fo) { load_rc (fo.path); }, [['f', function (a) { return "Source File: "; }, null, "source"]]);
270 function reinit (window) {
271     var path;
272     try {
273         path = load_rc();
274         window.minibuffer.message("Loaded: " + path);
275     } catch (e) {
276         window.minibuffer.message("Failed to load: "+path);
277     }
280 interactive("reinit",
281             "Reload the Conkeror rc file.",
282             function (I) { reinit(I.window); });
284 interactive("help-page", "Open the Conkeror help page.",
285             "find-url-new-buffer",
286             $browser_object = "chrome://conkeror-help/content/help.html");
288 interactive("tutorial", "Open the Conkeror tutorial.",
289             "find-url-new-buffer",
290             $browser_object = "chrome://conkeror-help/content/tutorial.html");
292 function univ_arg_to_number (prefix, default_value) {
293     if (prefix == null) {
294         if (default_value == null)
295             return 1;
296         else
297             return default_value;
298     }
299     if (typeof prefix == "object")
300         return prefix[0];
301     return prefix;
304 function eval_expression (window, s) {
305     // eval in the global scope.
307     // In addition, the following variables are available:
308     // var window;
309     var buffer = window.buffers.current;
310     var result = eval(s);
311     if (result !== undefined) {
312         window.minibuffer.message(String(result));
313     }
315 interactive("eval-expression",
316             "Evaluate JavaScript statements.",
317             function (I) {
318                 eval_expression(
319                     I.window,
320                     (yield I.minibuffer.read($prompt = "Eval:",
321                                              $history = "eval-expression",
322                                              $completer = javascript_completer(I.buffer))));
323             });
326 function show_extension_manager () {
327     return conkeror.window_watcher.openWindow(
328         null,
329         "chrome://mozapps/content/extensions/extensions.xul?type=extensions",
330         "ExtensionsWindow",
331         "resizable=yes,dialog=no",
332         null);
334 interactive("extensions",
335             "Open the extensions manager in a new window.",
336             show_extension_manager);
338 function print_buffer (buffer) {
339     buffer.top_frame.print();
341 interactive("print-buffer",
342             "Print the currently loaded page.",
343             function (I) { print_buffer(I.buffer); });
345 function view_partial_source (window, charset, selection) {
346     if (charset)
347         charset = "charset=" + charset;
348     window.window.openDialog("chrome://global/content/viewPartialSource.xul",
349                              "_blank", "scrollbars,resizable,chrome,dialog=no",
350                              null, charset, selection, 'selection');
352 //interactive ('view-partial-source', view_partial_source, I.current_window, I.content_charset, I.content_selection);
355 function  view_mathml_source (window, charset, target) {
356     if (charset)
357         charset = "charset=" + charset;
358     window.window.openDialog("chrome://global/content/viewPartialSource.xul",
359                              "_blank", "scrollbars,resizable,chrome,dialog=no",
360                              null, charset, target, 'mathml');
364 function send_key_as_event (window, element, combo) {
365     var split = unformat_key_combo(combo);
366     var event = window.document.createEvent("KeyboardEvent");
367     event.initKeyEvent(
368         "keypress",
369         true,
370         true,
371         null,
372         split.ctrlKey,
373         split.altKey,
374         split.shiftKey,
375         split.metaKey,
376         split.keyCode,
377         split.charCode);
378     if (element) {
379         return element.dispatchEvent (event);
380     } else {
381         return window.dispatchEvent (event);
382     }
386 function ensure_content_focused (buffer) {
387     var foc = buffer.focused_frame_or_null;
388     if (!foc)
389         buffer.top_frame.focus();
391 interactive("ensure-content-focused", "Ensure that the content document has focus.",
392             function (I) { ensure_content_focused(I.buffer); });
394 function network_set_online_status (status) {
395     status = !status;
396     io_service.manageOfflineStatus = false;
397     io_service.offline = status;
400 interactive("network-go-online", "Work online.",
401             function (I) { network_set_online_status (true); });
402 interactive("network-go-offline", "Work offline.",
403             function (I) { network_set_online_status (false); });
406 interactive("submit-form",
407             "Submit the form to which the focused element belongs.",
408             function (I) {
409                 var el = I.buffer.focused_element.parentNode;
410                 while (el && el.tagName != "FORM")
411                     el = el.parentNode;
412                 if (el)
413                     el.submit();
414             });
417  * Browser Object Commands
418  */
419 interactive("follow", null,
420             alternates(follow, follow_new_buffer, follow_new_window),
421             $browser_object = browser_object_links);
423 interactive("follow-top", null,
424             alternates(follow_current_buffer, follow_current_frame),
425             $browser_object = browser_object_frames,
426             $prompt = "Follow");
428 interactive("follow-new-buffer",
429             "Follow a link in a new buffer",
430             alternates(follow_new_buffer, follow_new_window),
431             $browser_object = browser_object_links,
432             $prompt = "Follow");
434 interactive("follow-new-buffer-background",
435             "Follow a link in a new buffer in the background",
436             alternates(follow_new_buffer_background, follow_new_window),
437             $browser_object = browser_object_links,
438             $prompt = "Follow");
440 interactive("follow-new-window",
441             "Follow a link in a new window",
442             follow_new_window,
443             $browser_object = browser_object_links,
444             $prompt = "Follow");
446 interactive("follow-current",
447             "Follow current object, normally the focused element.",
448             alternates(follow, follow_new_buffer, follow_new_window),
449             $browser_object = browser_object_focused_element);
451 interactive("follow-current-new-buffer",
452             "Follow current object, normally the focused element, in "+
453             "a new buffer.",
454             alternates(follow_new_buffer, follow_new_window),
455             $browser_object = browser_object_focused_element,
456             $prompt = "Follow");
458 interactive("follow-current-new-buffer-background",
459             "Follow current object, normally the focused element, in "+
460             "a new background buffer.",
461             alternates(follow_new_buffer_background, follow_new_window),
462             $browser_object = browser_object_focused_element,
463             $prompt = "Follow");
465 interactive("follow-current-new-window",
466             "Follow current object, normally the focused element, in "+
467             "a new window.",
468             follow_new_window,
469             $browser_object = browser_object_focused_element,
470             $prompt = "Follow");
472 interactive("find-url", "Open a URL in the current buffer",
473             alternates(follow_current_buffer, follow_new_buffer, follow_new_window),
474             $browser_object = browser_object_url);
476 interactive("find-url-new-buffer",
477             "Open a URL in a new buffer",
478             alternates(follow_new_buffer, follow_new_window),
479             $browser_object = browser_object_url,
480             $prompt = "Find url");
482 interactive("find-url-new-window", "Open a URL in a new window",
483             follow_new_window,
484             $browser_object = browser_object_url,
485             $prompt = "Find url");
487 interactive("find-alternate-url", "Edit the current URL in the minibuffer",
488             "find-url",
489             $browser_object =
490                 define_browser_object_class("alternate-url", null,
491                     function (I, prompt) {
492                         check_buffer(I.buffer, content_buffer);
493                         var result = yield I.buffer.window.minibuffer.read_url(
494                             $prompt = prompt,
495                             $initial_value = I.buffer.display_URI_string);
496                         yield co_return(result);
497                     }),
498             $prompt = "Find url");
501 interactive("up", "Go to the parent directory of the current URL",
502             "find-url",
503             $browser_object = browser_object_up_url);
505 interactive("home",
506             "Go to the homepage in the current buffer.", "follow",
507             $browser_object = function () { return homepage; });
509 interactive("make-window",
510             "Make a new window with the homepage.",
511             follow_new_window,
512             $browser_object = function () { return homepage; });
514 interactive("focus", null,
515             function (I) {
516                 var element = yield read_browser_object(I);
517                 browser_element_focus(I.buffer, element);
518             },
519             $browser_object = browser_object_frames);
522 interactive("save",
523     "Save a browser object.",
524     function (I) {
525         var element = yield read_browser_object(I);
526         var spec = load_spec(element);
527         var panel;
528         panel = create_info_panel(I.window, "download-panel",
529                                   [["downloading",
530                                     element_get_operation_label(element, "Saving"),
531                                     load_spec_uri_string(spec)],
532                                    ["mime-type", "Mime type:", load_spec_mime_type(spec)]]);
533         try {
534             var file = yield I.minibuffer.read_file_check_overwrite(
535                 $prompt = "Save as:",
536                 $initial_value = suggest_save_path_from_file_name(suggest_file_name(spec), I.buffer),
537                 $history = "save");
538         } finally {
539             panel.destroy();
540         }
541         save_uri(spec, file,
542                  $buffer = I.buffer,
543                  $use_cache = false);
544     },
545     $browser_object = browser_object_links);
548 interactive("copy", null,
549             function (I) {
550                 var element = yield read_browser_object(I);
551                 browser_element_copy(I.buffer, element);
552             },
553             $browser_object = browser_object_links);
555 interactive("paste-url", "Open a URL from the clipboard in the current buffer.",
556             alternates(follow_current_buffer, follow_new_buffer, follow_new_window),
557             $browser_object = browser_object_pasteurl);
559 interactive("paste-url-new-buffer", "Open a URL from the clipboard in a new buffer.",
560             alternates(follow_new_buffer, follow_new_window),
561             $browser_object = browser_object_pasteurl);
563 interactive("paste-url-new-window", "Open a URL from the clipboard in a new window.",
564             follow_new_window,
565             $browser_object = browser_object_pasteurl);
567 interactive("view-source", null,
568             alternates(view_source, view_source_new_buffer, view_source_new_window),
569             $browser_object = browser_object_frames);
572 interactive("shell-command-on-url",
573     "Run a shell command on the url of a browser object.",
574     function (I) {
575         var cwd = I.local.cwd;
576         var element = yield read_browser_object(I);
577         var spec = load_spec(element);
578         var uri = load_spec_uri_string(spec);
579         var panel;
580         panel = create_info_panel(I.window, "download-panel",
581                                   [["downloading",
582                                     element_get_operation_label(element, "Running on", "URI"),
583                                     load_spec_uri_string(spec)],
584                                    ["mime-type", "Mime type:", load_spec_mime_type(spec)]]);
585         try {
586             var cmd = yield I.minibuffer.read_shell_command(
587                 $cwd = cwd,
588                 $initial_value = load_spec_default_shell_command(spec));
589         } finally {
590             panel.destroy();
591         }
592         shell_command_with_argument_blind(cmd, uri, $cwd = cwd);
593     },
594     $browser_object = browser_object_url,
595     $prompt = "Shell command");
598 interactive("shell-command-on-file",
599     "Download a document to a temporary file and run a shell command on it.",
600     function (I) {
601         var cwd = I.local.cwd;
602         var element = yield read_browser_object(I);
603         var spec = load_spec(element);
604         var uri = load_spec_uri_string(spec);
605         var panel;
606         panel = create_info_panel(I.window, "download-panel",
607                                   [["downloading",
608                                     element_get_operation_label(element, "Running on"),
609                                     load_spec_uri_string(spec)],
610                                    ["mime-type", "Mime type:", load_spec_mime_type(spec)]]);
611         try {
612             var cmd = yield I.minibuffer.read_shell_command(
613                 $cwd = cwd,
614                 $initial_value = load_spec_default_shell_command(spec));
615         } finally {
616             panel.destroy();
617         }
618         yield browser_element_shell_command(I.buffer, element, cmd, cwd);
619     },
620     $browser_object = browser_object_links,
621     $prompt = "Shell command");
624 interactive("bookmark",
625     "Create a bookmark.",
626     function (I) {
627         var element = yield read_browser_object(I);
628         var spec = load_spec(element);
629         var uri_string = load_spec_uri_string(spec);
630         var panel;
631         panel = create_info_panel(I.window, "bookmark-panel",
632                                   [["bookmarking",
633                                     element_get_operation_label(element, "Bookmarking"),
634                                     uri_string]]);
635         try {
636             var title = yield I.minibuffer.read($prompt = "Bookmark with title:", $initial_value = load_spec_title(spec) || "");
637         } finally {
638             panel.destroy();
639         }
640         add_bookmark(uri_string, title);
641         I.minibuffer.message("Added bookmark: " + uri_string + " - " + title);
642     },
643     $browser_object = browser_object_frames);
646 interactive("save-page",
647     "Save a document, not including any embedded documents such as images "+
648     "and css.",
649     function (I) {
650         check_buffer(I.buffer, content_buffer);
651         var element = yield read_browser_object(I);
652         var spec = load_spec(element);
653         if (!load_spec_document(spec))
654             throw interactive_error("Element is not associated with a document.");
655         var suggested_path = suggest_save_path_from_file_name(suggest_file_name(spec), I.buffer);
657         var panel;
658         panel = create_info_panel(I.window, "download-panel",
659                                   [["downloading",
660                                     element_get_operation_label(element, "Saving"),
661                                     load_spec_uri_string(spec)],
662                                    ["mime-type", "Mime type:", load_spec_mime_type(spec)]]);
664         try {
665             var file = yield I.minibuffer.read_file_check_overwrite(
666                 $prompt = "Save page as:",
667                 $history = "save",
668                 $initial_value = suggested_path);
669         } finally {
670             panel.destroy();
671         }
673         save_uri(spec, file, $buffer = I.buffer);
674     },
675     $browser_object = browser_object_frames);
678 interactive("save-page-as-text",
679     "Save a page as plain text.",
680     function (I) {
681         check_buffer(I.buffer, content_buffer);
682         var element = yield read_browser_object(I);
683         var spec = load_spec(element);
684         var doc;
685         if (!(doc = load_spec_document(spec)))
686             throw interactive_error("Element is not associated with a document.");
687         var suggested_path = suggest_save_path_from_file_name(suggest_file_name(spec, "txt"), I.buffer);
689         var panel;
690         panel = create_info_panel(I.window, "download-panel",
691                                   [["downloading",
692                                     element_get_operation_label(element, "Saving", "as text"),
693                                     load_spec_uri_string(spec)],
694                                    ["mime-type", "Mime type:", load_spec_mime_type(spec)]]);
696         try {
697             var file = yield I.minibuffer.read_file_check_overwrite(
698                 $prompt = "Save page as text:",
699                 $history = "save",
700                 $initial_value = suggested_path);
701         } finally {
702             panel.destroy();
703         }
705         save_document_as_text(doc, file, $buffer = I.buffer);
706     },
707     $browser_object = browser_object_frames);
710 interactive("save-page-complete",
711     "Save a page and all supporting documents, including images, css, "+
712     "and child frame documents.",
713     function (I) {
714         check_buffer(I.buffer, content_buffer);
715         var element = yield read_browser_object(I);
716         var spec = load_spec(element);
717         var doc;
718         if (!(doc = load_spec_document(spec)))
719             throw interactive_error("Element is not associated with a document.");
720         var suggested_path = suggest_save_path_from_file_name(suggest_file_name(spec), I.buffer);
722         var panel;
723         panel = create_info_panel(I.window, "download-panel",
724                                   [["downloading",
725                                     element_get_operation_label(element, "Saving complete"),
726                                     load_spec_uri_string(spec)],
727                                    ["mime-type", "Mime type:", load_spec_mime_type(spec)]]);
729         try {
730             var file = yield I.minibuffer.read_file_check_overwrite(
731                 $prompt = "Save page complete:",
732                 $history = "save",
733                 $initial_value = suggested_path);
734             // FIXME: use proper read function
735             var dir = yield I.minibuffer.read_file(
736                 $prompt = "Data Directory:",
737                 $history = "save",
738                 $initial_value = file.path + ".support");
739         } finally {
740             panel.destroy();
741         }
743         save_document_complete(doc, file, dir, $buffer = I.buffer);
744     },
745     $browser_object = browser_object_frames);
748 function view_as_mime_type (I, target) {
749     I.target = target;
750     var element = yield read_browser_object(I);
751     var spec = load_spec(element);
753     if (target == null)
754         target = FOLLOW_CURRENT_FRAME;
756     if (!can_override_mime_type_for_uri(load_spec_uri(spec)))
757         throw interactive_error("Overriding the MIME type is not currently supported for non-HTTP URLs.");
759     var panel;
761     var mime_type = load_spec_mime_type(spec);
762     panel = create_info_panel(I.window, "download-panel",
763                               [["downloading",
764                                 element_get_operation_label(element, "View in browser"),
765                                 load_spec_uri_string(spec)],
766                                ["mime-type", "Mime type:", load_spec_mime_type(spec)]]);
769     try {
770         let suggested_type = mime_type;
771         if (gecko_viewable_mime_type_list.indexOf(suggested_type) == -1)
772             suggested_type = "text/plain";
773         mime_type = yield I.minibuffer.read_gecko_viewable_mime_type(
774             $prompt = "View internally as",
775             $initial_value = suggested_type,
776             $select);
777         override_mime_type_for_next_load(load_spec_uri(spec), mime_type);
778         browser_object_follow(I.buffer, target, spec);
779     } finally {
780         panel.destroy();
781     }
783 function view_as_mime_type_new_buffer (I) {
784     yield view_as_mime_type(I, OPEN_NEW_BUFFER);
786 function view_as_mime_type_new_window (I) {
787     yield view_as_mime_type(I, OPEN_NEW_WINDOW);
789 interactive("view-as-mime-type",
790             "Display a browser object in the browser using the specified MIME type.",
791             alternates(view_as_mime_type,
792                        view_as_mime_type_new_buffer,
793                        view_as_mime_type_new_window),
794             $browser_object = browser_object_frames);
797 interactive("reload-with-charset",
798             null, // TODO: Add a docstring.
799             function (I) {
800                 var forced_charset = yield I.minibuffer.read($prompt = "Charset:");
801                 reload(I.buffer, false, null, forced_charset);
802             });
804 interactive("yank",
805             "Paste the contents of the clipboard",
806             function (I) {
807                 I.buffer.mark_active = false;
808                 I.buffer.do_command("cmd_paste");
809             });
811 interactive("kill-region",
812             "Kill (\"cut\") the selected text.",
813             function (I) {
814                 I.buffer.mark_active = false;
815                 I.buffer.do_command("cmd_cut");
816             });
818 interactive("kill-ring-save",
819             "Save the region as if killed, but don't kill it.",
820             function (I) {
821                 I.buffer.mark_active = false;
822                 I.buffer.do_command("cmd_copy");
823             });