]> git.donarmstrong.com Git - dactyl.git/blobdiff - common/modules/io.jsm
Import r6923 from upstream hg supporting Firefox up to 22.0a1
[dactyl.git] / common / modules / io.jsm
index 5eefcc17b6bb6aeaceecae247a49df9035a36846..9e717d74ed51ebd217ea017e821b017e7a7ef7c7 100644 (file)
@@ -1,22 +1,24 @@
 // Copyright (c) 2006-2008 by Martin Stubenschrott <stubenschrott@vimperator.org>
-// Copyright (c) 2007-2011 by Doug Kearns <dougkearns@gmail.com>
-// Copyright (c) 2008-2011 by Kris Maglione <maglione.k@gmail.com>
+// Copyright (c) 2007-2012 by Doug Kearns <dougkearns@gmail.com>
+// Copyright (c) 2008-2012 Kris Maglione <maglione.k@gmail.com>
 // Some code based on Venkman
 //
 // This work is licensed for reuse under an MIT license. Details are
 // given in the LICENSE.txt file included with this file.
-/* use strict */
+"use strict";
 
 try {
 
-Components.utils.import("resource://dactyl/bootstrap.jsm");
 defineModule("io", {
     exports: ["IO", "io"],
     require: ["services"]
-}, this);
+});
 
-this.lazyRequire("config", ["config"]);
-this.lazyRequire("contexts", ["Contexts", "contexts"]);
+lazyRequire("config", ["config"]);
+lazyRequire("contexts", ["Contexts", "contexts"]);
+lazyRequire("storage", ["File", "storage"]);
+lazyRequire("styles", ["styles"]);
+lazyRequire("template", ["template"]);
 
 // TODO: why are we passing around strings rather than file objects?
 /**
@@ -41,26 +43,6 @@ var IO = Module("io", {
 
             this._lastRunCommand = ""; // updated whenever the users runs a command with :!
             this._scriptNames = [];
-
-            this.downloadListener = {
-                onDownloadStateChange: function (state, download) {
-                    if (download.state == services.downloadManager.DOWNLOAD_FINISHED) {
-                        let url   = download.source.spec;
-                        let title = download.displayName;
-                        let file  = download.targetFile.path;
-                        let size  = download.size;
-
-                        dactyl.echomsg({ domains: [util.getHost(url)], message: _("io.downloadFinished", title, file) },
-                                       1, modules.commandline.ACTIVE_WINDOW);
-                        modules.autocommands.trigger("DownloadPost", { url: url, title: title, file: file, size: size });
-                    }
-                },
-                onStateChange:    function () {},
-                onProgressChange: function () {},
-                onSecurityChange: function () {}
-            };
-
-            services.downloadManager.addListener(this.downloadListener);
         },
 
         CommandFileMode: Class("CommandFileMode", modules.CommandMode, {
@@ -84,10 +66,6 @@ var IO = Module("io", {
             }
         }),
 
-        destroy: function destroy() {
-            services.downloadManager.removeListener(this.downloadListener);
-        },
-
         /**
          * Returns all directories named *name* in 'runtimepath'.
          *
@@ -173,7 +151,7 @@ var IO = Module("io", {
                         dactyl.triggerObserver("io.source", context, file, file.lastModifiedTime);
                     }
 
-                    if (/\.js,$/.test(filename))
+                    if (/\.jsm$/.test(filename))
                         sourceJSM();
                     else if (/\.js$/.test(filename)) {
                         try {
@@ -190,12 +168,14 @@ var IO = Module("io", {
                                 sourceJSM();
                             }
                             else {
+                                if (e instanceof Finished)
+                                    return;
                                 if (e.fileName && !(e instanceof FailedAssertion))
                                     try {
                                         e.fileName = util.fixURI(e.fileName);
                                         if (e.fileName == uri.spec)
                                             e.fileName = filename;
-                                        e.echoerr = <>{e.fileName}:{e.lineNumber}: {e}</>;
+                                        e.echoerr = [e.fileName, ":", e.lineNumber, ": ", e].join("");
                                     }
                                     catch (e) {}
                                 throw e;
@@ -331,14 +311,19 @@ var IO = Module("io", {
      *
      * @returns {File}
      */
-    createTempFile: function createTempFile(name) {
-        if (name instanceof Ci.nsIFile)
+    createTempFile: function createTempFile(name, type) {
+        if (name instanceof Ci.nsIFile) {
             var file = name.clone();
+            if (!type || type == "file")
+                file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, octal(666));
+            else
+                file.createUnique(Ci.nsIFile.DIRECTORY_TYPE, octal(777));
+        }
         else {
             file = services.directory.get("TmpD", Ci.nsIFile);
             file.append(this.config.tempFile + (name ? "." + name : ""));
+            file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, octal(666));
         }
-        file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, octal(600));
 
         services.externalApp.deleteTemporaryFileOnExit(file);
 
@@ -378,7 +363,7 @@ var IO = Module("io", {
         file = util.getFile(file);
         if (file && file.exists() && file.isFile() && file.isReadable()) {
             // let jar = services.zipReader.getZip(file); Crashes.
-            let jar = services.ZipReader(file);
+            let jar = services.ZipReader(file.file);
             try {
                 let filter = RegExp("^" + util.regexp.escape(decodeURI(path))
                                     + "[^/]*/?$");
@@ -414,7 +399,8 @@ var IO = Module("io", {
         if (bin instanceof File || File.isAbsolutePath(bin))
             return this.File(bin);
 
-        let dirs = services.environment.get("PATH").split(config.OS.isWindows ? ";" : ":");
+        let dirs = services.environment.get("PATH")
+                           .split(config.OS.pathListSep);
         // Windows tries the CWD first TODO: desirable?
         if (config.OS.isWindows)
             dirs = [io.cwd].concat(dirs);
@@ -460,7 +446,7 @@ var IO = Module("io", {
             return -1;
         }
 
-        let process = services.Process(file);
+        let process = services.Process(file.file);
         process.run(false, args.map(String), args.length);
         try {
             if (callable(blocking))
@@ -487,10 +473,12 @@ var IO = Module("io", {
     // TODO: when https://bugzilla.mozilla.org/show_bug.cgi?id=68702 is
     // fixed use that instead of a tmpfile
     /**
-     * Runs *command* in a subshell and returns the output in a string. The
-     * shell used is that specified by the 'shell' option.
+     * Runs *command* in a subshell and returns the output. The shell used is
+     * that specified by the 'shell' option.
      *
-     * @param {string} command The command to run.
+     * @param {string|[string]} command The command to run. This can be a shell
+     *      command string or an array of strings (a command and arguments)
+     *      which will be escaped and concatenated.
      * @param {string} input Any input to be provided to the command on stdin.
      * @param {function(object)} callback A callback to be called when
      *      the command completes. @optional
@@ -556,7 +544,8 @@ var IO = Module("io", {
      *     otherwise, the return value of *func*.
      */
     withTempFiles: function withTempFiles(func, self, checked, ext) {
-        let args = array(util.range(0, func.length)).map(bind("createTempFile", this, ext)).array;
+        let args = array(util.range(0, func.length))
+                    .map(bind("createTempFile", this, ext)).array;
         try {
             if (!args.every(util.identity))
                 return false;
@@ -588,7 +577,7 @@ var IO = Module("io", {
      */
     PATH_SEP: deprecated("File.PATH_SEP", { get: function PATH_SEP() File.PATH_SEP })
 }, {
-    commands: function init_commands(dactyl, modules, window) {
+    commands: function initCommands(dactyl, modules, window) {
         const { commands, completion, io } = modules;
 
         commands.add(["cd", "chd[ir]"],
@@ -651,6 +640,7 @@ var IO = Module("io", {
 
                 try {
                     file.write(lines.join("\n"));
+                    dactyl.echomsg(_("io.writing", file.path.quote()), 2);
                 }
                 catch (e) {
                     dactyl.echoerr(_("io.notWriteable", file.path.quote()));
@@ -662,24 +652,65 @@ var IO = Module("io", {
                 completer: function (context) completion.file(context, true)
             });
 
-        commands.add(["mks[yntax]"],
-            "Generate a Vim syntax file",
+        commands.add(["mkv[imruntime]"],
+            "Create and install Vim runtime files for " + config.appName,
             function (args) {
-                let runtime = config.OS.isWindows ? "~/vimfiles/" : "~/.vim/";
-                let file = io.File(runtime + "syntax/" + config.name + ".vim");
-                if (args.length)
-                    file = io.File(args[0]);
+                dactyl.assert(args.length <= 1, _("io.oneFileAllowed"));
+
+                if (args.length) {
+                    var rtDir = io.File(args[0]);
+                    dactyl.assert(rtDir.exists(), _("io.noSuchDir", rtDir.path.quote()));
+                }
+                else
+                    rtDir = io.File(config.OS.isWindows ? "~/vimfiles/" : "~/.vim/");
+
+                dactyl.assert(!rtDir.exists() || rtDir.isDirectory(), _("io.eNotDir", rtDir.path.quote()));
+
+                let rtItems = { ftdetect: {}, ftplugin: {}, syntax: {} };
+
+                // require bang if any of the paths exist
+                for (let [type, item] in iter(rtItems)) {
+                    let file = io.File(rtDir).child(type, config.name + ".vim");
+                    dactyl.assert(!file.exists() || args.bang, _("io.exists", file.path.quote()));
+                    item.file = file;
+                }
+
+                rtItems.ftdetect.template = // {{{
+literal(/*" Vim filetype detection file
+<header>
+
+au BufNewFile,BufRead *<name>rc*,*.<fileext> set filetype=<name>
+*/);//}}}
+                rtItems.ftplugin.template = // {{{
+literal(/*" Vim filetype plugin file
+<header>
 
-                if (file.exists() && file.isDirectory() || args[0] && /\/$/.test(args[0]))
-                    file.append(config.name + ".vim");
-                dactyl.assert(!file.exists() || args.bang, _("io.exists"));
+if exists("b:did_ftplugin")
+  finish
+endif
+let b:did_ftplugin = 1
+
+let s:cpo_save = &cpo
+set cpo&vim
 
-                let template = util.compileMacro(<![CDATA[
-" Vim syntax file
-" Language:         Pentadactyl configuration file
-" Maintainer:       Doug Kearns <dougkearns@gmail.com>
+let b:undo_ftplugin = "setl com< cms< fo< ofu< | unlet! b:browsefilter"
 
-" TODO: make this <name> specific - shared dactyl config?
+setlocal comments=:\"
+setlocal commentstring=\"%s
+setlocal formatoptions-=t formatoptions+=croql
+setlocal omnifunc=syntaxcomplete#Complete
+
+if has("gui_win32") && !exists("b:browsefilter")
+    let b:browsefilter = "<appname> Config Files (*.<fileext>)\t*.<fileext>\n" .
+        \ "All Files (*.*)\t*.*\n"
+endif
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
+*/);//}}}
+                rtItems.syntax.template = // {{{
+literal(/*" Vim syntax file
+<header>
 
 if exists("b:current_syntax")
   finish
@@ -756,11 +787,13 @@ let b:current_syntax = "<name>"
 let &cpo = s:cpo_save
 unlet s:cpo_save
 
-" vim: tw=130 et ts=4 sw=4:
-]]>, true);
+" vim: tw=130 et ts=8 sts=4 sw=4:
+*/);//}}}
+
+                const { options } = modules;
 
                 const WIDTH = 80;
-                function wrap(prefix, items, sep) {
+                function wrap(prefix, items, sep) {//{{{
                     sep = sep || " ";
                     let width = 0;
                     let lines = [];
@@ -777,11 +810,16 @@ unlet s:cpo_save
                     }
                     lines.last.pop();
                     return lines.map(function (l) l.join("")).join("\n").replace(/\s+\n/gm, "\n");
-                }
+                }//}}}
 
-                const { commands, options } = modules;
-                file.write(template({
+                let params = { // {{{
+                    header: ['" Language:    ' + config.appName + ' configuration file',
+                             '" Maintainer:  Doug Kearns <dougkearns@gmail.com>',
+                             '" Version:     ' + config.version].join("\n"),
                     name: config.name,
+                    appname: config.appName,
+                    fileext: config.fileExtension,
+                    maintainer: "Doug Kearns <dougkearns@gmail.com>",
                     autocommands: wrap("syn keyword " + config.name + "AutoEvent ",
                                        keys(config.autocommands)),
                     commands: wrap("syn keyword " + config.name + "Command ",
@@ -792,11 +830,22 @@ unlet s:cpo_save
                                         array(o.realNames for (o in options) if (o.type == "boolean"))
                                             .flatten().map(String.quote),
                                         ", ") + "]"
-                }));
+                }; // }}}
+
+                for (let { file, template } in values(rtItems)) {
+                    try {
+                        file.write(util.compileMacro(template, true)(params));
+                        dactyl.echomsg(_("io.writing", file.path.quote()), 2);
+                    }
+                    catch (e) {
+                        dactyl.echoerr(_("io.notWriteable", file.path.quote()));
+                        dactyl.log(_("error.notWriteable", file.path, e.message));
+                    }
+                }
             }, {
                 argCount: "?",
                 bang: true,
-                completer: function (context) completion.file(context, true),
+                completer: function (context) completion.directory(context, true),
                 literal: 1
             });
 
@@ -869,7 +918,7 @@ unlet s:cpo_save
                     result.output += "\n" + _("io.shellReturn", result.returnValue);
 
                 modules.commandline.command = args.commandName.replace("run", "$& ") + arg;
-                modules.commandline.commandOutput(<span highlight="CmdOutput">{result.output}</span>);
+                modules.commandline.commandOutput(["span", { highlight: "CmdOutput" }, result.output]);
 
                 modules.autocommands.trigger("ShellCmdPost", {});
             }, {
@@ -880,7 +929,7 @@ unlet s:cpo_save
                 literal: 0
             });
     },
-    completion: function init_completion(dactyl, modules, window) {
+    completion: function initCompletion(dactyl, modules, window) {
         const { completion, io } = modules;
 
         completion.charset = function (context) {
@@ -992,7 +1041,7 @@ unlet s:cpo_save
         };
 
         completion.addUrlCompleter("file", "Local files", function (context, full) {
-            let match = util.regexp(<![CDATA[
+            let match = util.regexp(literal(/*
                 ^
                 (?P<prefix>
                     (?P<proto>
@@ -1003,7 +1052,7 @@ unlet s:cpo_save
                 )
                 (?P<path> \/[^\/]* )?
                 $
-            ]]>, "x").exec(context.filter);
+            */), "x").exec(context.filter);
             if (match) {
                 if (!match.path) {
                     context.key = match.proto;
@@ -1028,7 +1077,7 @@ unlet s:cpo_save
                     completion.file(context, full);
         });
     },
-    javascript: function init_javascript(dactyl, modules, window) {
+    javascript: function initJavascript(dactyl, modules, window) {
         modules.JavaScript.setCompleter([File, File.expandPath],
             [function (context, obj, args) {
                 context.quote[2] = "";
@@ -1047,7 +1096,7 @@ unlet s:cpo_save
             input: true
         });
     },
-    options: function init_options(dactyl, modules, window) {
+    options: function initOptions(dactyl, modules, window) {
         const { completion, options } = modules;
 
         var shell, shellcmdflag;