X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=common%2Fmodules%2Fmessages.jsm;fp=common%2Fmodules%2Fmessages.jsm;h=bca366992cf0b3f49a5752a97fcb4ae3ab20a26d;hb=9044153cb63835e39b9de8ec4ade237c03e3888a;hp=f1f4de1324a3d02103e7313294775671135ef629;hpb=70740024f9c028c1fd63e1a1850ab062ff956054;p=dactyl.git diff --git a/common/modules/messages.jsm b/common/modules/messages.jsm index f1f4de1..bca3669 100644 --- a/common/modules/messages.jsm +++ b/common/modules/messages.jsm @@ -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); + }]); } });