//
// 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 {
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) {
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) {}
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) {}
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) {
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))
})
}, {
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);
+ }]);
}
});