X-Git-Url: https://git.donarmstrong.com/?p=dactyl.git;a=blobdiff_plain;f=common%2Fmodules%2Ftemplate.jsm;h=47fd94db2214804890fd76f9f85f26bdd788570b;hp=09300d0e888a419ac729d90439ed92d1b53bb29b;hb=8b6fcae7eaa413bc62d645d2d0c99835c47265e6;hpb=5ebd29f56d17f62011cdd596b1d351947ee534ff diff --git a/common/modules/template.jsm b/common/modules/template.jsm index 09300d0..47fd94d 100644 --- a/common/modules/template.jsm +++ b/common/modules/template.jsm @@ -1,17 +1,16 @@ -// Copyright (c) 2008-2011 by Kris Maglione +// Copyright (c) 2008-2012 Kris Maglione // // 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"; let global = this; -Components.utils.import("resource://dactyl/bootstrap.jsm"); defineModule("template", { exports: ["Binding", "Template", "template"], require: ["util"] -}, this); +}); -default xml namespace = XHTML; +lazyRequire("help", ["help"]); var Binding = Class("Binding", { init: function (node, nodes) { @@ -92,27 +91,6 @@ var Binding = Class("Binding", { }); var Template = Module("Template", { - add: function add(a, b) a + b, - join: function join(c) function (a, b) a + c + b, - - map: function map(iter, func, sep, interruptable) { - XML.ignoreWhitespace = XML.prettyPrinting = false; - if (typeof iter.length == "number") // FIXME: Kludge? - iter = array.iterValues(iter); - let res = <>; - let n = 0; - for each (let i in Iterator(iter)) { - let val = func(i, n); - if (val == undefined) - continue; - if (n++ && sep) - res += sep; - if (interruptable && n % interruptable == 0) - util.threadYield(true, true); - res += val; - } - return res; - }, bindings: { Button: Class("Button", Binding, { @@ -171,22 +149,42 @@ var Template = Module("Template", { }) }, - bookmarkDescription: function (item, text) - <> - { - !(item.extra && item.extra.length) ? "" : - - ({ - template.map(item.extra, function (e) - <>{e[0]}: {e[1]}, - <> ) - })  + map: function map(iter, func, sep, interruptable) { + if (typeof iter.length == "number") // FIXME: Kludge? + iter = array.iterValues(iter); + + let res = []; + let n = 0; + for each (let i in Iterator(iter)) { + let val = func(i, n); + if (val == undefined) + continue; + if (n++ && sep) + res.push(sep); + if (interruptable && n % interruptable == 0) + util.threadYield(true, true); + res.push(val); } - {text || ""} - , + return res; + }, + + + bookmarkDescription: function (item, text) [ + !(item.extra && item.extra.length) ? [] : + ["span", { highlight: "URLExtra" }, + " (", + template.map(item.extra, function (e) + ["", e[0], ": ", + ["span", { highlight: e[2] }, e[1]]], + "\u00a0"), + ")\u00a0"], + ["a", { identifier: item.id == null ? "" : item.id, + "dactyl:command": item.command || "", + href: item.item.url, highlight: "URL" }, + text || ""] + ], - filter: function (str) {str}, + filter: function (str) ["span", { highlight: "Filter" }, str], completionRow: function completionRow(item, highlightGroup) { if (typeof icon == "function") @@ -201,17 +199,15 @@ var Template = Module("Template", { var desc = this.processor[1].call(this, item, item.description); } - XML.ignoreWhitespace = XML.prettyPrinting = false; - // - return
- -
  • {text} 
  • -
  • {desc} 
  • -
    ; - //
    + return ["div", { highlight: highlightGroup || "CompItem", style: "white-space: nowrap" }, + /* The non-breaking spaces prevent empty elements + * from pushing the baseline down and enlarging + * the row. + */ + ["li", { highlight: "CompResult " + item.highlight }, + text, "\u00a0"], + ["li", { highlight: "CompDesc" }, + desc, "\u00a0"]]; }, helpLink: function (token, text, type) { @@ -225,14 +221,16 @@ var Template = Module("Template", { topic = topic.slice(2); if (help.initialized && !Set.has(help.tags, topic)) - return {text || token}; + return ["span", { highlight: type || ""}, text || token]; - XML.ignoreWhitespace = XML.prettyPrinting = false; type = type || (/^'.*'$/.test(token) ? "HelpOpt" : /^\[.*\]$|^E\d{3}$/.test(token) ? "HelpTopic" : /^:\w/.test(token) ? "HelpEx" : "HelpKey"); - return {text || topic}; + return ["a", { highlight: "InlineHelpLink " + type, tag: topic, + href: "dactyl://help-tag/" + topic, + "dactyl:command": "dactyl.help" }, + text || topic]; }, HelpLink: function (token) { if (!help.initialized) @@ -245,28 +243,28 @@ var Template = Module("Template", { topic = topic.slice(2); if (help.initialized && !Set.has(help.tags, topic)) - return <>{token}; + return token; - XML.ignoreWhitespace = XML.prettyPrinting = false; let tag = (/^'.*'$/.test(token) ? "o" : /^\[.*\]$|^E\d{3}$/.test(token) ? "t" : /^:\w/.test(token) ? "ex" : "k"); topic = topic.replace(/^'(.*)'$/, "$1"); - return <{tag} xmlns={NS}>{topic}; + return [tag, { xmlns: "dactyl" }, topic]; }, linkifyHelp: function linkifyHelp(str, help) { - let re = util.regexp( [/\s]|^) (?P '[\w-]+' | :(?:[\w-]+!?|!) | (?:._)?<[\w-]+>\w* | \b[a-zA-Z]_(?:[\w[\]]+|.) | \[[\w-;]+\] | E\d{3} ) (?= [[\)!,:;./\s]|$) - ]]>, "gx"); + */), "gx"); return this.highlightSubstrings(str, (function () { for (let res in re.iterate(str)) yield [res.index + res.pre.length, res.tag.length]; - })(), template[help ? "HelpLink" : "helpLink"]); + })(), this[help ? "HelpLink" : "helpLink"]); }, + // Fixes some strange stack rewinds on NS_ERROR_OUT_OF_MEMORY // exceptions that we can't catch. stringify: function stringify(arg) { @@ -282,12 +280,12 @@ var Template = Module("Template", { } }, - _sandbox: Class.Memoize(function () Cu.Sandbox(global, { wantXrays: false })), + _sandbox: Class.Memoize(function () Cu.Sandbox(Cu.getGlobalForObject(global), + { wantXrays: false })), // if "processStrings" is true, any passed strings will be surrounded by " and // any line breaks are displayed as \n highlight: function highlight(arg, processStrings, clip, bw) { - XML.ignoreWhitespace = XML.prettyPrinting = false; // some objects like window.JSON or getBrowsers()._browsers need the try/catch try { let str = this.stringify(arg); @@ -295,44 +293,44 @@ var Template = Module("Template", { str = util.clip(str, clip); switch (arg == null ? "undefined" : typeof arg) { case "number": - return {str}; + return ["span", { highlight: "Number" }, str]; case "string": if (processStrings) str = str.quote(); - return {str}; + return ["span", { highlight: "String" }, str]; case "boolean": - return {str}; + return ["span", { highlight: "Boolean" }, str]; case "function": if (arg instanceof Ci.nsIDOMElement) // wtf? return util.objectToString(arg, !bw); str = str.replace("/* use strict */ \n", "/* use strict */ "); if (processStrings) - return {str.replace(/\{(.|\n)*(?:)/g, "{ ... }")}; - <>}; /* Vim */ + return ["span", { highlight: "Function" }, + str.replace(/\{(.|\n)*(?:)/g, "{ ... }")]; arg = String(arg).replace("/* use strict */ \n", "/* use strict */ "); - return <>{arg}; + return arg; case "undefined": - return {arg}; + return ["span", { highlight: "Null" }, "undefined"]; case "object": if (arg instanceof Ci.nsIDOMElement) return util.objectToString(arg, !bw); + if (arg instanceof util.Magic) + return String(arg); - // for java packages value.toString() would crash so badly - // that we cannot even try/catch it - if (/^\[JavaPackage.*\]$/.test(arg)) - return <>[JavaPackage]; if (processStrings && false) - str = template.highlightFilter(str, "\n", function () ^J); - return {str}; + str = template._highlightFilter(str, "\n", + function () ["span", { highlight: "NonText" }, + "^J"]); + return ["span", { highlight: "Object" }, str]; case "xml": return arg; default: - return ]]>; + return ""; } } catch (e) { - return ]]>; + return ""; } }, @@ -344,7 +342,6 @@ var Template = Module("Template", { if (filter.length == 0) return; - XML.ignoreWhitespace = XML.prettyPrinting = false; let lcstr = String.toLowerCase(str); let lcfilter = filter.toLowerCase(); let start = 0; @@ -363,14 +360,13 @@ var Template = Module("Template", { }, highlightSubstrings: function highlightSubstrings(str, iter, highlight) { - XML.ignoreWhitespace = XML.prettyPrinting = false; - if (typeof str == "xml") + if (!isString(str)) return str; + if (str == "") - return <>{str}; + return DOM.DOMString(str); - str = String(str).replace(" ", "\u00a0"); - let s = <>; + let s = [""]; let start = 0; let n = 0, _i; for (let [i, length, args] in iter) { @@ -378,176 +374,138 @@ var Template = Module("Template", { break; _i = i; - XML.ignoreWhitespace = false; - s += <>{str.substring(start, i)}; - s += highlight.apply(this, Array.concat(args || str.substr(i, length))); + s.push(str.substring(start, i), + highlight.apply(this, Array.concat(args || str.substr(i, length)))); start = i + length; } - return s + <>{str.substr(start)}; + s.push(str.substr(start)); + return s; }, highlightURL: function highlightURL(str, force) { if (force || /^[a-zA-Z]+:\/\//.test(str)) - return {util.losslessDecodeURI(str)}; + return ["a", { highlight: "URL", href: str }, + util.losslessDecodeURI(str)]; else return str; }, - icon: function (item, text) <> - {item.icon ? : <>}{text} - , + icon: function (item, text) [ + ["span", { highlight: "CompIcon" }, + item.icon ? ["img", { src: item.icon }] : []], + ["span", { class: "td-strut" }], + text + ], jumps: function jumps(index, elems) { - XML.ignoreWhitespace = XML.prettyPrinting = false; - // - return - - - - - - - - { - this.map(Iterator(elems), function ([idx, val]) - - - - - - - - ) - } -
    {_("title.Jump")}{_("title.HPos")}{_("title.VPos")}{_("title.Title")}{_("title.URI")}
    {idx == index ? ">" : ""}{Math.abs(idx - index)}{val.offset ? val.offset.x : ""}{val.offset ? val.offset.y : ""}{val.title}{util.losslessDecodeURI(val.URI.spec)}
    ; - //
    + return ["table", {}, + ["tr", { style: "text-align: left;", highlight: "Title" }, + ["th", { colspan: "2" }, _("title.Jump")], + ["th", {}, _("title.HPos")], + ["th", {}, _("title.VPos")], + ["th", {}, _("title.Title")], + ["th", {}, _("title.URI")]], + this.map(Iterator(elems), function ([idx, val]) + ["tr", {}, + ["td", { class: "indicator" }, idx == index ? ">" : ""], + ["td", {}, Math.abs(idx - index)], + ["td", {}, val.offset ? val.offset.x : ""], + ["td", {}, val.offset ? val.offset.y : ""], + ["td", { style: "width: 250px; max-width: 500px; overflow: hidden;" }, val.title], + ["td", {}, + ["a", { href: val.URI.spec, highlight: "URL jump-list" }, + util.losslessDecodeURI(val.URI.spec)]]])]; }, + options: function options(title, opts, verbose) { - XML.ignoreWhitespace = XML.prettyPrinting = false; - // - return - - - - { - this.map(opts, function (opt) - - - ) - } -
    --- {title} ---
    -
    {opt.pre}{opt.name}{opt.value}{ - opt.isDefault || opt.default == null ? "" : (default: {opt.default}) - }
    { - verbose && opt.setFrom ?
    Last set from {template.sourceLink(opt.setFrom)}
    : <> - } -
    ; - //
    + return ["table", {}, + ["tr", { highlight: "Title", align: "left" }, + ["th", {}, "--- " + title + " ---"]], + this.map(opts, function (opt) + ["tr", {}, + ["td", {}, + ["div", { highlight: "Message" }, + ["span", { style: opt.isDefault ? "" : "font-weight: bold" }, + opt.pre, opt.name], + ["span", {}, opt.value], + opt.isDefault || opt.default == null ? "" : ["span", { class: "extra-info" }, " (default: ", opt.default, ")"]], + verbose && opt.setFrom ? ["div", { highlight: "Message" }, + " Last set from ", + template.sourceLink(opt.setFrom)] : ""]])]; }, sourceLink: function (frame) { let url = util.fixURI(frame.filename || "unknown"); let path = util.urlPath(url); - XML.ignoreWhitespace = XML.prettyPrinting = false; - return { - path + ":" + frame.lineNumber - }; + return ["a", { "dactyl:command": "buffer.viewSource", + href: url, path: path, line: frame.lineNumber, + highlight: "URL" }, + path + ":" + frame.lineNumber]; }, table: function table(title, data, indent) { - XML.ignoreWhitespace = XML.prettyPrinting = false; - let table = // - - - - - { - this.map(data, function (datum) - - - - ) - } -
    {title}
    {datum[0]}{datum[1]}
    ; - //
    - if (table.tr.length() > 1) + let table = ["table", {}, + ["tr", { highlight: "Title", align: "left" }, + ["th", { colspan: "2" }, title]], + this.map(data, function (datum) + ["tr", {}, + ["td", { style: "font-weight: bold; min-width: 150px; padding-left: " + (indent || "2ex") }, datum[0]], + ["td", {}, datum[1]]])]; + + if (table[3].length) return table; }, tabular: function tabular(headings, style, iter) { + let self = this; // TODO: This might be mind-bogglingly slow. We'll see. - XML.ignoreWhitespace = XML.prettyPrinting = false; - // - return - - { - this.map(headings, function (h) - ) - } - - { - this.map(iter, function (row) - - { - template.map(Iterator(row), function ([i, d]) - ) - } - ) - } -
    {h}
    {d}
    ; - //
    + return ["table", {}, + ["tr", { highlight: "Title", align: "left" }, + this.map(headings, function (h) + ["th", {}, h])], + this.map(iter, function (row) + ["tr", {}, + self.map(Iterator(row), function ([i, d]) + ["td", { style: style[i] || "" }, d])])]; }, usage: function usage(iter, format) { - XML.ignoreWhitespace = XML.prettyPrinting = false; + let self = this; + format = format || {}; - let desc = format.description || function (item) template.linkifyHelp(item.description); + let desc = format.description || function (item) self.linkifyHelp(item.description); let help = format.help || function (item) item.name; function sourceLink(frame) { - let source = template.sourceLink(frame); - source.@NS::hint = source.text(); + let source = self.sourceLink(frame); + source[1]["dactyl:hint"] = source[2]; return source; } - // - return - { format.headings ? - - - { - this.map(format.headings, function (h) ) - } - - : "" - } - { format.columns ? - - { - this.map(format.columns, function (c) ) - } - : "" - } - { + return ["table", {}, + format.headings ? + ["thead", { highlight: "UsageHead" }, + ["tr", { highlight: "Title", align: "left" }, + this.map(format.headings, function (h) ["th", {}, h])]] : + [], + format.columns ? + ["colgroup", {}, + this.map(format.columns, function (c) ["col", { style: c }])] : + [], + ["tbody", { highlight: "UsageBody" }, this.map(iter, function (item) - - - { item.columns ? template.map(item.columns, function (c) ) : "" } - - ) - } -
    {h}
    - { - let (name = item.name || item.names[0], frame = item.definedAt) - !frame ? name : - template.helpLink(help(item), name, "Title") + - {_("io.definedAt")} {sourceLink(frame)} - } - {c}{desc(item)}
    ; - //
    + // Urgh. + let (name = item.name || item.names[0], frame = item.definedAt) + ["tr", { highlight: "UsageItem" }, + ["td", { style: "padding-right: 2em;" }, + ["span", { highlight: "Usage Link" }, + !frame ? name : + [self.helpLink(help(item), name, "Title"), + ["span", { highlight: "LinkInfo" }, + _("io.definedAt"), " ", + sourceLink(frame)]]]], + item.columns ? self.map(item.columns, function (c) ["td", {}, c]) : [], + ["td", {}, desc(item)]])]] } });