mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2026-02-17 15:05:45 +01:00
Death to E4X and stuff.
This commit is contained in:
@@ -2,18 +2,16 @@
|
||||
//
|
||||
// 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;
|
||||
defineModule("template", {
|
||||
exports: ["Binding", "Template", "template", "template_"],
|
||||
exports: ["Binding", "Template", "template"],
|
||||
require: ["util"]
|
||||
});
|
||||
|
||||
lazyRequire("help", ["help"]);
|
||||
|
||||
default xml namespace = XHTML;
|
||||
|
||||
var Binding = Class("Binding", {
|
||||
init: function (node, nodes) {
|
||||
this.node = node;
|
||||
@@ -93,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, {
|
||||
@@ -172,388 +149,6 @@ var Template = Module("Template", {
|
||||
})
|
||||
},
|
||||
|
||||
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]}</span></>,
|
||||
<> </>)
|
||||
}) </span>
|
||||
}
|
||||
<a xmlns:dactyl={NS} identifier={item.id == null ? "" : item.id} dactyl:command={item.command || ""}
|
||||
href={item.item.url} highlight="URL">{text || ""}</a>
|
||||
</>,
|
||||
|
||||
filter: function (str) <span highlight="Filter">{str}</span>,
|
||||
|
||||
completionRow: function completionRow(item, highlightGroup) {
|
||||
if (typeof icon == "function")
|
||||
icon = icon();
|
||||
|
||||
if (highlightGroup) {
|
||||
var text = item[0] || "";
|
||||
var desc = item[1] || "";
|
||||
}
|
||||
else {
|
||||
var text = this.processor[0].call(this, item, item.result);
|
||||
var desc = this.processor[1].call(this, item, item.description);
|
||||
}
|
||||
|
||||
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) {
|
||||
if (!help.initialized)
|
||||
util.dactyl.initHelp();
|
||||
|
||||
let topic = token; // FIXME: Evil duplication!
|
||||
if (/^\[.*\]$/.test(topic))
|
||||
topic = topic.slice(1, -1);
|
||||
else if (/^n_/.test(topic))
|
||||
topic = topic.slice(2);
|
||||
|
||||
if (help.initialized && !Set.has(help.tags, topic))
|
||||
return <span highlight={type || ""}>{text || token}</span>;
|
||||
|
||||
XML.ignoreWhitespace = XML.prettyPrinting = false;
|
||||
type = type || (/^'.*'$/.test(token) ? "HelpOpt" :
|
||||
/^\[.*\]$|^E\d{3}$/.test(token) ? "HelpTopic" :
|
||||
/^:\w/.test(token) ? "HelpEx" : "HelpKey");
|
||||
|
||||
return <a highlight={"InlineHelpLink " + type} tag={topic} href={"dactyl://help-tag/" + topic} dactyl:command="dactyl.help" xmlns:dactyl={NS}>{text || topic}</a>;
|
||||
},
|
||||
HelpLink: function (token) {
|
||||
if (!help.initialized)
|
||||
util.dactyl.initHelp();
|
||||
|
||||
let topic = token; // FIXME: Evil duplication!
|
||||
if (/^\[.*\]$/.test(topic))
|
||||
topic = topic.slice(1, -1);
|
||||
else if (/^n_/.test(topic))
|
||||
topic = topic.slice(2);
|
||||
|
||||
if (help.initialized && !Set.has(help.tags, topic))
|
||||
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}</{tag}>;
|
||||
},
|
||||
linkifyHelp: function linkifyHelp(str, help) {
|
||||
let re = util.regexp(literal(/*
|
||||
(?P<pre> [/\s]|^)
|
||||
(?P<tag> '[\w-]+' | :(?:[\w-]+!?|!) | (?:._)?<[\w-]+>\w* | \b[a-zA-Z]_(?:[\w[\]]+|.) | \[[\w-;]+\] | E\d{3} )
|
||||
(?= [[\)!,:;./\s]|$)
|
||||
*/), "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"]);
|
||||
},
|
||||
|
||||
// Fixes some strange stack rewinds on NS_ERROR_OUT_OF_MEMORY
|
||||
// exceptions that we can't catch.
|
||||
stringify: function stringify(arg) {
|
||||
if (!callable(arg))
|
||||
return String(arg);
|
||||
|
||||
try {
|
||||
this._sandbox.arg = arg;
|
||||
return Cu.evalInSandbox("String(arg)", this._sandbox);
|
||||
}
|
||||
finally {
|
||||
this._sandbox.arg = null;
|
||||
}
|
||||
},
|
||||
|
||||
_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);
|
||||
if (clip)
|
||||
str = util.clip(str, clip);
|
||||
switch (arg == null ? "undefined" : typeof arg) {
|
||||
case "number":
|
||||
return <span highlight="Number">{str}</span>;
|
||||
case "string":
|
||||
if (processStrings)
|
||||
str = str.quote();
|
||||
return <span highlight="String">{str}</span>;
|
||||
case "boolean":
|
||||
return <span highlight="Boolean">{str}</span>;
|
||||
case "function":
|
||||
if (arg instanceof Ci.nsIDOMElement) // wtf?
|
||||
return util.objectToString(arg, !bw);
|
||||
|
||||
str = str.replace("/* use strict */ \n", "/* use strict */ ");
|
||||
if (processStrings)
|
||||
return <span highlight="Function">{str.replace(/\{(.|\n)*(?:)/g, "{ ... }")}</span>;
|
||||
<>}</>; /* Vim */
|
||||
arg = String(arg).replace("/* use strict */ \n", "/* use strict */ ");
|
||||
return <>{arg}</>;
|
||||
case "undefined":
|
||||
return <span highlight="Null">{arg}</span>;
|
||||
case "object":
|
||||
if (arg instanceof Ci.nsIDOMElement)
|
||||
return util.objectToString(arg, !bw);
|
||||
if (arg instanceof util.Magic)
|
||||
return <>{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 () <span highlight="NonText">^J</span>);
|
||||
return <span highlight="Object">{str}</span>;
|
||||
case "xml":
|
||||
return arg;
|
||||
default:
|
||||
return <![CDATA[<unknown type>]]>;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
return <![CDATA[<unknown>]]>;
|
||||
}
|
||||
},
|
||||
|
||||
highlightFilter: function highlightFilter(str, filter, highlight, isURI) {
|
||||
if (isURI)
|
||||
str = util.losslessDecodeURI(str);
|
||||
|
||||
return this.highlightSubstrings(str, (function () {
|
||||
if (filter.length == 0)
|
||||
return;
|
||||
|
||||
XML.ignoreWhitespace = XML.prettyPrinting = false;
|
||||
let lcstr = String.toLowerCase(str);
|
||||
let lcfilter = filter.toLowerCase();
|
||||
let start = 0;
|
||||
while ((start = lcstr.indexOf(lcfilter, start)) > -1) {
|
||||
yield [start, filter.length];
|
||||
start += filter.length;
|
||||
}
|
||||
})(), highlight || template.filter);
|
||||
},
|
||||
|
||||
highlightRegexp: function highlightRegexp(str, re, highlight) {
|
||||
return this.highlightSubstrings(str, (function () {
|
||||
for (let res in util.regexp.iterate(re, str))
|
||||
yield [res.index, res[0].length, res.wholeMatch ? [res] : res];
|
||||
})(), highlight || template.filter);
|
||||
},
|
||||
|
||||
highlightSubstrings: function highlightSubstrings(str, iter, highlight) {
|
||||
XML.ignoreWhitespace = XML.prettyPrinting = false;
|
||||
if (typeof str == "xml")
|
||||
return str;
|
||||
if (str == "")
|
||||
return <>{str}</>;
|
||||
|
||||
str = String(str).replace(" ", "\u00a0");
|
||||
let s = <></>;
|
||||
let start = 0;
|
||||
let n = 0, _i;
|
||||
for (let [i, length, args] in iter) {
|
||||
if (i == _i || i < _i)
|
||||
break;
|
||||
_i = i;
|
||||
|
||||
XML.ignoreWhitespace = false;
|
||||
s += <>{str.substring(start, i)}</>;
|
||||
s += highlight.apply(this, Array.concat(args || str.substr(i, length)));
|
||||
start = i + length;
|
||||
}
|
||||
return s + <>{str.substr(start)}</>;
|
||||
},
|
||||
|
||||
highlightURL: function highlightURL(str, force) {
|
||||
if (force || /^[a-zA-Z]+:\/\//.test(str))
|
||||
return <a highlight="URL" href={str}>{util.losslessDecodeURI(str)}</a>;
|
||||
else
|
||||
return str;
|
||||
},
|
||||
|
||||
icon: function (item, text) <>
|
||||
<span highlight="CompIcon">{item.icon ? <img src={item.icon}/> : <></>}</span><span class="td-strut"/>{text}
|
||||
</>,
|
||||
|
||||
jumps: function jumps(index, elems) {
|
||||
XML.ignoreWhitespace = XML.prettyPrinting = false;
|
||||
// <e4x>
|
||||
return <table>
|
||||
<tr style="text-align: left;" highlight="Title">
|
||||
<th colspan="2">{_("title.Jump")}</th>
|
||||
<th>{_("title.HPos")}</th>
|
||||
<th>{_("title.VPos")}</th>
|
||||
<th>{_("title.Title")}</th>
|
||||
<th>{_("title.URI")}</th>
|
||||
</tr>
|
||||
{
|
||||
this.map(Iterator(elems), function ([idx, val])
|
||||
<tr>
|
||||
<td class="indicator">{idx == index ? ">" : ""}</td>
|
||||
<td>{Math.abs(idx - index)}</td>
|
||||
<td>{val.offset ? val.offset.x : ""}</td>
|
||||
<td>{val.offset ? val.offset.y : ""}</td>
|
||||
<td style="width: 250px; max-width: 500px; overflow: hidden;">{val.title}</td>
|
||||
<td><a href={val.URI.spec} highlight="URL jump-list">{util.losslessDecodeURI(val.URI.spec)}</a></td>
|
||||
</tr>)
|
||||
}
|
||||
</table>;
|
||||
// </e4x>
|
||||
},
|
||||
|
||||
options: function options(title, opts, verbose) {
|
||||
XML.ignoreWhitespace = XML.prettyPrinting = false;
|
||||
// <e4x>
|
||||
return <table>
|
||||
<tr highlight="Title" align="left">
|
||||
<th>--- {title} ---</th>
|
||||
</tr>
|
||||
{
|
||||
this.map(opts, function (opt)
|
||||
<tr>
|
||||
<td>
|
||||
<div highlight="Message"
|
||||
><span style={opt.isDefault ? "" : "font-weight: bold"}>{opt.pre}{opt.name}</span><span>{opt.value}</span>{
|
||||
opt.isDefault || opt.default == null ? "" : <span class="extra-info"> (default: {opt.default})</span>
|
||||
}</div>{
|
||||
verbose && opt.setFrom ? <div highlight="Message"> Last set from {template.sourceLink(opt.setFrom)}</div> : <></>
|
||||
}
|
||||
</td>
|
||||
</tr>)
|
||||
}
|
||||
</table>;
|
||||
// </e4x>
|
||||
},
|
||||
|
||||
sourceLink: function (frame) {
|
||||
let url = util.fixURI(frame.filename || "unknown");
|
||||
let path = util.urlPath(url);
|
||||
|
||||
XML.ignoreWhitespace = XML.prettyPrinting = false;
|
||||
return <a xmlns:dactyl={NS} dactyl:command="buffer.viewSource"
|
||||
href={url} path={path} line={frame.lineNumber}
|
||||
highlight="URL">{
|
||||
path + ":" + frame.lineNumber
|
||||
}</a>;
|
||||
},
|
||||
|
||||
table: function table(title, data, indent) {
|
||||
XML.ignoreWhitespace = XML.prettyPrinting = false;
|
||||
let table = // <e4x>
|
||||
<table>
|
||||
<tr highlight="Title" align="left">
|
||||
<th colspan="2">{title}</th>
|
||||
</tr>
|
||||
{
|
||||
this.map(data, function (datum)
|
||||
<tr>
|
||||
<td style={"font-weight: bold; min-width: 150px; padding-left: " + (indent || "2ex")}>{datum[0]}</td>
|
||||
<td>{datum[1]}</td>
|
||||
</tr>)
|
||||
}
|
||||
</table>;
|
||||
// </e4x>
|
||||
if (table.tr.length() > 1)
|
||||
return table;
|
||||
},
|
||||
|
||||
tabular: function tabular(headings, style, iter) {
|
||||
// TODO: This might be mind-bogglingly slow. We'll see.
|
||||
XML.ignoreWhitespace = XML.prettyPrinting = false;
|
||||
// <e4x>
|
||||
return <table>
|
||||
<tr highlight="Title" align="left">
|
||||
{
|
||||
this.map(headings, function (h)
|
||||
<th>{h}</th>)
|
||||
}
|
||||
</tr>
|
||||
{
|
||||
this.map(iter, function (row)
|
||||
<tr>
|
||||
{
|
||||
template.map(Iterator(row), function ([i, d])
|
||||
<td style={style[i] || ""}>{d}</td>)
|
||||
}
|
||||
</tr>)
|
||||
}
|
||||
</table>;
|
||||
// </e4x>
|
||||
},
|
||||
|
||||
usage: function usage(iter, format) {
|
||||
XML.ignoreWhitespace = XML.prettyPrinting = false;
|
||||
format = format || {};
|
||||
let desc = format.description || function (item) template.linkifyHelp(item.description);
|
||||
let help = format.help || function (item) item.name;
|
||||
function sourceLink(frame) {
|
||||
let source = template.sourceLink(frame);
|
||||
source.@NS::hint = source.text();
|
||||
return source;
|
||||
}
|
||||
// <e4x>
|
||||
return <table>
|
||||
{ format.headings ?
|
||||
<thead highlight="UsageHead">
|
||||
<tr highlight="Title" align="left">
|
||||
{
|
||||
this.map(format.headings, function (h) <th>{h}</th>)
|
||||
}
|
||||
</tr>
|
||||
</thead> : ""
|
||||
}
|
||||
{ format.columns ?
|
||||
<colgroup>
|
||||
{
|
||||
this.map(format.columns, function (c) <col style={c}/>)
|
||||
}
|
||||
</colgroup> : ""
|
||||
}
|
||||
<tbody highlight="UsageBody">{
|
||||
this.map(iter, function (item)
|
||||
<tr highlight="UsageItem">
|
||||
<td style="padding-right: 2em;">
|
||||
<span highlight="Usage Link">{
|
||||
let (name = item.name || item.names[0], frame = item.definedAt)
|
||||
!frame ? name :
|
||||
template.helpLink(help(item), name, "Title") +
|
||||
<span highlight="LinkInfo" xmlns:dactyl={NS}>{_("io.definedAt")} {sourceLink(frame)}</span>
|
||||
}</span>
|
||||
</td>
|
||||
{ item.columns ? template.map(item.columns, function (c) <td>{c}</td>) : "" }
|
||||
<td>{desc(item)}</td>
|
||||
</tr>)
|
||||
}</tbody>
|
||||
</table>;
|
||||
// </e4x>
|
||||
}
|
||||
});
|
||||
|
||||
var Template_ = Module("Template_", {
|
||||
map: function map(iter, func, sep, interruptable) {
|
||||
if (typeof iter.length == "number") // FIXME: Kludge?
|
||||
iter = array.iterValues(iter);
|
||||
@@ -626,7 +221,7 @@ var Template_ = Module("Template_", {
|
||||
topic = topic.slice(2);
|
||||
|
||||
if (help.initialized && !Set.has(help.tags, topic))
|
||||
return <span highlight={type || ""}>{text || token}</span>;
|
||||
return ["span", { highlight: type || ""}, text || token];
|
||||
|
||||
type = type || (/^'.*'$/.test(token) ? "HelpOpt" :
|
||||
/^\[.*\]$|^E\d{3}$/.test(token) ? "HelpTopic" :
|
||||
|
||||
Reference in New Issue
Block a user