]> git.donarmstrong.com Git - dactyl.git/blobdiff - common/modules/messages.jsm
Import 1.0rc1 supporting Firefox up to 11.*
[dactyl.git] / common / modules / messages.jsm
index f1f4de1324a3d02103e7313294775671135ef629..bca366992cf0b3f49a5752a97fcb4ae3ab20a26d 100644 (file)
@@ -2,7 +2,7 @@
 //
 // 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 {
 
@@ -12,25 +12,18 @@ defineModule("messages", {
     require: ["services", "util"]
 }, this);
 
-// TODO: Lazy instantiation
 var Messages = Module("messages", {
 
     init: function init(name) {
         let self = this;
-        name = name || "messages";
-
-        this.bundles = array.uniq([JSMLoader.getTarget("dactyl://locale/" + name + ".properties"),
-                                   JSMLoader.getTarget("dactyl://locale-local/" + name + ".properties"),
-                                   "resource://dactyl-locale/en-US/" + name + ".properties",
-                                   "resource://dactyl-locale-local/en-US/" + name + ".properties"])
-                            .map(services.stringBundle.createBundle)
-                            .filter(function (bundle) { try { bundle.getSimpleEnumeration(); return true; } catch (e) { return false; } });
+        this.name = name || "messages";
 
         this._ = Class("_", String, {
             init: function _(message) {
                 this.args = arguments;
             },
-            message: Class.memoize(function () {
+            instance: {},
+            message: Class.Memoize(function () {
                 let message = this.args[0];
 
                 if (this.args.length > 1) {
@@ -42,27 +35,35 @@ var Messages = Module("messages", {
             valueOf: function valueOf() this.message,
             toString: function toString() this.message
         });
-
-        let seen = {};
-        for (let { key } in this.iterate()) {
-            if (!Set.add(seen, key))
-                this._[key] = this[key] = {
-                    __noSuchMethod__: function __(prop, args) self._.apply(self, [prop].concat(args))
-                };
-        }
     },
 
-    iterate: function () let (bundle = this.bundles[0])
-        iter(prop.QueryInterface(Ci.nsIPropertyElement) for (prop in iter(bundle.getSimpleEnumeration()))),
-
     cleanup: function cleanup() {
         services.stringBundle.flushBundles();
     },
 
+    bundles: Class.Memoize(function ()
+        array.uniq([JSMLoader.getTarget("dactyl://locale/" + this.name + ".properties"),
+                    JSMLoader.getTarget("dactyl://locale-local/" + this.name + ".properties"),
+                    "resource://dactyl-locale/en-US/" + this.name + ".properties",
+                    "resource://dactyl-locale-local/en-US/" + this.name + ".properties"])
+             .map(services.stringBundle.createBundle)
+             .filter(function (bundle) { try { bundle.getSimpleEnumeration(); return true; } catch (e) { return false; } })),
+
+    iterate: function () {
+        let seen = {};
+        for (let bundle in values(this.bundles))
+            for (let { key, value } in iter(bundle.getSimpleEnumeration(), Ci.nsIPropertyElement))
+                if (!Set.add(seen, key))
+                    yield [key, value];
+    },
+
     get: function get(value, default_) {
         for (let bundle in values(this.bundles))
             try {
-                return bundle.GetStringFromName(value);
+                let res = bundle.GetStringFromName(value);
+                if (res.slice(0, 2) == "+ ")
+                    return res.slice(2).replace(/\s+/g, " ");
+                return res;
             }
             catch (e) {}
 
@@ -75,7 +76,10 @@ var Messages = Module("messages", {
     format: function format(value, args, default_) {
         for (let bundle in values(this.bundles))
             try {
-                return bundle.formatStringFromName(value, args, args.length);
+                let res = bundle.formatStringFromName(value, args, args.length);
+                if (res.slice(0, 2) == "+ ")
+                    return res.slice(2).replace(/\s+/g, " ");
+                return res;
             }
             catch (e) {}
 
@@ -83,8 +87,51 @@ var Messages = Module("messages", {
         if (arguments.length < 3) // Do *not* localize these strings
             util.reportError(Error("Invalid locale string: " + value));
         return arguments.length > 2 ? default_ : value;
-    }
+    },
 
+    /**
+     * Exports known localizable strings to a properties file.
+     *
+     * @param {string|nsIFile} {file} The file to which to export
+     *      the strings.
+     */
+    export: function export_(file) {
+        let { Buffer, commands, hints, io, mappings, modes, options, sanitizer } = overlay.activeModules;
+        file = io.File(file);
+
+        function properties(base, iter_, prop) iter(function _properties() {
+            function key() [base, obj.identifier || obj.name].concat(Array.slice(arguments)).join(".").replace(/[\\:=]/g, "\\$&");
+
+            prop = prop || "description";
+            for (var obj in iter_) {
+                if (!obj.hive || obj.hive.name !== "user") {
+                    yield key(prop) + " = " + obj[prop];
+
+                    if (iter_.values)
+                        for (let [k, v] in isArray(obj.values) ? array.iterValues(obj.values) : iter(obj.values))
+                            yield key("values", k) + " = " + v;
+
+                    for (let opt in values(obj.options))
+                        yield key("options", opt.names[0]) + " = " + opt.description;
+
+                    if (obj.deprecated)
+                        yield key("deprecated") + " = " + obj.deprecated;
+                }
+            }
+        }()).toArray();
+
+        file.write(
+            array(commands.allHives.map(function (h) properties("command", h)))
+                          .concat(modes.all.map(function (m)
+                              properties("map", values(mappings.builtin.getStack(m)
+                                                               .filter(function (map) map.modes[0] == m)))))
+                          .concat(properties("mode", values(modes.all.filter(function (m) !m.hidden))))
+                          .concat(properties("option", options))
+                          .concat(properties("hintmode", values(hints.modes), "prompt"))
+                          .concat(properties("pageinfo", values(Buffer.pageInfo), "title"))
+                          .concat(properties("sanitizeitem", values(sanitizer.itemMap)))
+                .flatten().uniq().join("\n"));
+    }
 }, {
     Localized: Class("Localized", Class.Property, {
         init: function init(prop, obj) {
@@ -108,7 +155,10 @@ var Messages = Module("messages", {
                         function getter(key, default_) function getter() messages.get([name, key].join("."), default_);
 
                         if (value != null) {
-                            var name = [this.constructor.className.toLowerCase(), this.identifier || this.name, prop].join(".");
+                            var name = [this.constructor.className.toLowerCase(),
+                                        this.identifier || this.name,
+                                        prop].join(".");
+
                             if (!isObject(value))
                                 value = messages.get(name, value);
                             else if (isArray(value))
@@ -137,12 +187,17 @@ var Messages = Module("messages", {
     })
 }, {
     javascript: function initJavascript(dactyl, modules, window) {
-        modules.JavaScript.setCompleter([this._, this.get, this.format], [
-            function (context) {
-                context.keys = { text: "key", description: "value" };
-                return messages.iterate();
-            }
+        let { JavaScript } = modules;
+
+        JavaScript.setCompleter([this._, this.get, this.format], [
+            function (context) messages.iterate()
         ]);
+
+        JavaScript.setCompleter([this.export],
+            [function (context, obj, args) {
+                context.quote[2] = "";
+                modules.completion.file(context, true);
+            }]);
     }
 });