diff --git a/common/content/hints.js b/common/content/hints.js index 5f3a3bf2..e3ae23b5 100644 --- a/common/content/hints.js +++ b/common/content/hints.js @@ -761,6 +761,11 @@ var Hints = Module("hints", { this.addMode("V", "View hint source in external editor", function (elem, loc) buffer.viewSource(loc, true)); this.addMode("y", "Yank hint location", function (elem, loc) editor.setRegister(null, loc, true)); this.addMode("Y", "Yank hint description", function (elem) editor.setRegister(null, elem.textContent || "", true)); + this.addMode("A", "Yank hint anchor url", function (elem) { + let uri = elem.ownerDocument.documentURIObject.clone(); + uri.ref = elem.id; + dactyl.clipboardWrite(uri.spec, true); + }); this.addMode("c", "Open context menu", function (elem) DOM(elem).contextmenu()); this.addMode("i", "Show image", function (elem) dactyl.open(elem.src)); this.addMode("I", "Show image in a new tab", function (elem) dactyl.open(elem.src, dactyl.NEW_TAB)); @@ -1271,6 +1276,7 @@ var Hints = Module("hints", { "regexpmap", { "[iI]": "img", "[asOTvVWy]": [":-moz-any-link", "area[href]", "img[src]", "iframe[src]"], + "[A]": ["[id]"], "[f]": "body", "[F]": ["body", "code", "div", "html", "p", "pre", "span"], "[S]": ["input:not([type=hidden])", "textarea", "button", "select"] @@ -1280,11 +1286,13 @@ var Hints = Module("hints", { getKey: function (val, default_) let (res = array.nth(this.value, function (re) let (match = re.exec(val)) match && match[0] == val, 0)) res ? res.matcher : default_, - setter: function (vals) { + parse: function parse(val) { + let vals = parse.supercall(this, val); for (let value in values(vals)) value.matcher = DOM.compileMatcher(Option.splitList(value.result)); return vals; }, + testValues: function testValues(vals, validator) vals.every(function (re) Option.splitList(re).every(validator)), validator: DOM.validateMatcher }); diff --git a/common/locale/en-US/options.xml b/common/locale/en-US/options.xml index f195845f..24566080 100644 --- a/common/locale/en-US/options.xml +++ b/common/locale/en-US/options.xml @@ -694,6 +694,7 @@ &option.extendedhinttags.type; [asOTvVWy]:':-moz-any-link',area[href],img[src],iframe[src], + [A]:[id], [f]:body, [F]:body,code,div,html,p,pre,span, [iI]:img, diff --git a/common/modules/base.jsm b/common/modules/base.jsm index ff4a7b4a..2187e95c 100644 --- a/common/modules/base.jsm +++ b/common/modules/base.jsm @@ -1762,7 +1762,7 @@ Object.keys(array).forEach(function (k) { }); Object.getOwnPropertyNames(Array.prototype).forEach(function (k) { - if (!(k in iterProto)) + if (!(k in iterProto) && callable(Array.prototype[k])) iterProto[k] = function () { let ary = iter(this).toArray(); let res = ary[k].apply(ary, arguments); diff --git a/common/modules/options.jsm b/common/modules/options.jsm index 9fb2899b..dacafbdd 100644 --- a/common/modules/options.jsm +++ b/common/modules/options.jsm @@ -339,7 +339,9 @@ var Option = Class("Option", { if (isArray(defaultValue)) defaultValue = defaultValue.map(Option.quote).join(","); else if (isObject(defaultValue)) - defaultValue = iter(defaultValue).map(function (val) val.map(Option.quote).join(":")).join(","); + defaultValue = iter(defaultValue).map(function (val) val.map(function (v) Option.quote(v, /:/)) + .join(":")) + .join(","); if (isArray(defaultValue)) defaultValue = defaultValue.map(Option.quote).join(","); @@ -446,7 +448,7 @@ var Option = Class("Option", { }, unparseRegexp: function unparseRegexp(re, quoted) re.bang + Option.quote(util.regexp.getSource(re), /^!|:/) + - (typeof re.result === "boolean" ? "" : ":" + (quoted ? re.result : Option.quote(re.result))), + (typeof re.result === "boolean" ? "" : ":" + (quoted ? re.result : Option.quote(re.result, /:/))), parseSite: function parseSite(pattern, result, rest) { if (isArray(rest)) // Called by Array.map @@ -455,7 +457,7 @@ var Option = Class("Option", { let [, bang, filter] = /^(!?)(.*)/.exec(pattern); filter = Option.dequote(filter).trim(); - let quote = this.keepQuotes ? util.identity : Option.quote; + let quote = this.keepQuotes ? util.identity : function (v) Option.quote(v, /:/); return update(Styles.matchFilter(filter), { bang: bang, @@ -491,7 +493,7 @@ var Option = Class("Option", { stringlist: function (vals) vals.map(Option.quote).join(","), - stringmap: function (vals) [Option.quote(k, /:/) + ":" + Option.quote(v) for ([k, v] in Iterator(vals))].join(","), + stringmap: function (vals) [Option.quote(k, /:/) + ":" + Option.quote(v, /:/) for ([k, v] in Iterator(vals))].join(","), regexplist: function (vals) vals.join(","), get regexpmap() this.regexplist, diff --git a/pentadactyl/NEWS b/pentadactyl/NEWS index a9b1526b..c2901f64 100644 --- a/pentadactyl/NEWS +++ b/pentadactyl/NEWS @@ -84,6 +84,7 @@ • The command line is now hidden by default. Added c, C, and M to 'guioptions'. [b4] • Hints mode improvements, including: + - Added [;A] extended hint mode. [rc2] - Added g; continued extended hints mode, which allows selecting multiple hints. Removed ;F. [b1] - Hints are now updated after scrolling and window resizing. [b3]