mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-23 13:42:27 +01:00
Show the default styles in :highlight, etc.
This commit is contained in:
@@ -26,8 +26,6 @@ the provisions above, a recipient may use your version of this file under
|
|||||||
the terms of any one of the MPL, the GPL or the LGPL.
|
the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
}}} ***** END LICENSE BLOCK *****/
|
}}} ***** END LICENSE BLOCK *****/
|
||||||
|
|
||||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
|
|
||||||
const Point = new Struct("x", "y");
|
const Point = new Struct("x", "y");
|
||||||
|
|
||||||
function Buffer() //{{{
|
function Buffer() //{{{
|
||||||
@@ -35,241 +33,6 @@ function Buffer() //{{{
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
////////////////////// PRIVATE SECTION /////////////////////////////////////////
|
////////////////////// PRIVATE SECTION /////////////////////////////////////////
|
||||||
/////////////////////////////////////////////////////////////////////////////{{{
|
/////////////////////////////////////////////////////////////////////////////{{{
|
||||||
|
|
||||||
const highlightClasses = ["Boolean", "ErrorMsg", "Filter", "Function", "InfoMsg", "Keyword",
|
|
||||||
"LineNr", "ModeMsg", "MoreMsg", "Normal", "Null", "Number", "Object", "Question",
|
|
||||||
"StatusLine", "StatusLineBroken", "StatusLineSecure", "String", "TabClose", "TabIcon",
|
|
||||||
"TabIconNumber", "TabNumber", "TabText", "Tag", "Title", "URL", "WarningMsg",
|
|
||||||
["Hint", ".liberator-hint", "*"],
|
|
||||||
["Search", ".__liberator-search", "*"],
|
|
||||||
["Bell", "#liberator-visualbell"],
|
|
||||||
];
|
|
||||||
const highlightDocs = "chrome://liberator/content/buffer.xhtml,chrome://browser/content/browser.xul";
|
|
||||||
|
|
||||||
var highlight = storage.newMap("highlight", false);
|
|
||||||
|
|
||||||
const util = modules.util;
|
|
||||||
const arrayIter = util.Array.iterator;
|
|
||||||
|
|
||||||
function Styles(name, store, serial)
|
|
||||||
{
|
|
||||||
/* Can't reference liberator or Components inside Styles --
|
|
||||||
* they're members of the window object, which disappear
|
|
||||||
* with this window.
|
|
||||||
*/
|
|
||||||
const sleep = liberator.sleep;
|
|
||||||
const storage = modules.storage;
|
|
||||||
const consoleService = Components.classes["@mozilla.org/consoleservice;1"]
|
|
||||||
.getService(Components.interfaces.nsIConsoleService);
|
|
||||||
const ios = Components.classes["@mozilla.org/network/io-service;1"]
|
|
||||||
.getService(Components.interfaces.nsIIOService);
|
|
||||||
const sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
|
|
||||||
.getService(Components.interfaces.nsIStyleSheetService);
|
|
||||||
const XHTML = "http://www.w3.org/1999/xhtml";
|
|
||||||
const namespace = "@namespace html url(" + XHTML + ");\n" +
|
|
||||||
"@namespace xul url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);\n";
|
|
||||||
const Sheet = new Struct("name", "sites", "css", "ref");
|
|
||||||
|
|
||||||
let cssUri = function (css) "chrome-data:text/css," + encodeURI(css);
|
|
||||||
|
|
||||||
let userSheets = [];
|
|
||||||
let systemSheets = [];
|
|
||||||
let userNames = {};
|
|
||||||
let systemNames = {};
|
|
||||||
|
|
||||||
this.__iterator__ = function () Iterator(userSheets.concat(systemSheets));
|
|
||||||
this.__defineGetter__("systemSheets", function () Iterator(systemSheets));
|
|
||||||
this.__defineGetter__("userSheets", function () Iterator(userSheets));
|
|
||||||
this.__defineGetter__("systemNames", function () Iterator(systemNames));
|
|
||||||
this.__defineGetter__("userNames", function () Iterator(userNames));
|
|
||||||
|
|
||||||
this.addSheet = function (name, filter, css, system, force)
|
|
||||||
{
|
|
||||||
let sheets = system ? systemSheets : userSheets;
|
|
||||||
let names = system ? systemNames : userNames;
|
|
||||||
if (name && name in names)
|
|
||||||
this.removeSheet(name, null, null, null, system);
|
|
||||||
|
|
||||||
let sheet = sheets.filter(function (s) s.sites.join(",") == filter && s.css == css)[0];
|
|
||||||
if (!sheet)
|
|
||||||
sheet = new Sheet(name, filter.split(","), css, null);
|
|
||||||
|
|
||||||
if (sheet.ref == null) // Not registered yet
|
|
||||||
{
|
|
||||||
sheet.ref = [];
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.registerSheet(cssUri(wrapCSS(sheet)), !force);
|
|
||||||
}
|
|
||||||
catch (e)
|
|
||||||
{
|
|
||||||
return e.echoerr || e;
|
|
||||||
}
|
|
||||||
sheets.push(sheet);
|
|
||||||
}
|
|
||||||
if (name)
|
|
||||||
{
|
|
||||||
sheet.ref.push(name);
|
|
||||||
names[name] = sheet;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.findSheets = function (name, filter, css, index, system)
|
|
||||||
{
|
|
||||||
let sheets = system ? systemSheets : userSheets;
|
|
||||||
let names = system ? systemNames : userNames;
|
|
||||||
|
|
||||||
// Grossly inefficient.
|
|
||||||
let matches = [k for ([k, v] in sheets)];
|
|
||||||
if (index)
|
|
||||||
matches = String(index).split(",").filter(function (i) i in sheets);
|
|
||||||
if (name)
|
|
||||||
matches = matches.filter(function (i) sheets[i] == names[name]);
|
|
||||||
if (css)
|
|
||||||
matches = matches.filter(function (i) sheets[i].css == css);
|
|
||||||
if (filter)
|
|
||||||
matches = matches.filter(function (i) sheets[i].sites.indexOf(filter) >= 0);
|
|
||||||
return matches;
|
|
||||||
},
|
|
||||||
|
|
||||||
this.removeSheet = function (name, filter, css, index, system)
|
|
||||||
{
|
|
||||||
let self = this;
|
|
||||||
let sheets = system ? systemSheets : userSheets;
|
|
||||||
let names = system ? systemNames : userNames;
|
|
||||||
|
|
||||||
if (filter && filter.indexOf(",") > -1)
|
|
||||||
return filter.split(",").reduce(
|
|
||||||
function (n, f) n + self.removeSheet(name, f, index, system), 0);
|
|
||||||
|
|
||||||
if (filter == undefined)
|
|
||||||
filter = "";
|
|
||||||
|
|
||||||
let matches = this.findSheets(name, filter, css, index, system);
|
|
||||||
if (matches.length == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (let [,i] in Iterator(matches.reverse()))
|
|
||||||
{
|
|
||||||
let sheet = sheets[i];
|
|
||||||
if (name)
|
|
||||||
{
|
|
||||||
sheet.ref.splice(sheet.ref.indexOf(name));
|
|
||||||
delete names[name];
|
|
||||||
}
|
|
||||||
if (!sheet.ref.length)
|
|
||||||
{
|
|
||||||
sheets.splice(i);
|
|
||||||
this.unregisterSheet(cssUri(wrapCSS(sheet)));
|
|
||||||
}
|
|
||||||
// Filter out the given site, and re-add if there are any left
|
|
||||||
if (filter)
|
|
||||||
{
|
|
||||||
let sites = sheet.sites.filter(function (f) f != filter);
|
|
||||||
if (sites.length)
|
|
||||||
this.addSheet(name, sites.join(","), css, system, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return matches.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.registerSheet = function (uri, doCheckSyntax, reload)
|
|
||||||
{
|
|
||||||
if (doCheckSyntax)
|
|
||||||
checkSyntax(uri);
|
|
||||||
if (reload)
|
|
||||||
this.unregisterSheet(uri);
|
|
||||||
uri = ios.newURI(uri, null, null);
|
|
||||||
if (reload || !sss.sheetRegistered(uri, sss.USER_SHEET))
|
|
||||||
sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.unregisterSheet = function (uri)
|
|
||||||
{
|
|
||||||
uri = ios.newURI(uri, null, null);
|
|
||||||
if (sss.sheetRegistered(uri, sss.USER_SHEET))
|
|
||||||
sss.unregisterSheet(uri, sss.USER_SHEET);
|
|
||||||
}
|
|
||||||
|
|
||||||
function wrapCSS(sheet)
|
|
||||||
{
|
|
||||||
let filter = sheet.sites;
|
|
||||||
let css = sheet.css;
|
|
||||||
if (filter[0] == "*")
|
|
||||||
return namespace + css;
|
|
||||||
let selectors = filter.map(function (part) (/[*]$/.test(part) ? "url-prefix" :
|
|
||||||
/[\/:]/.test(part) ? "url"
|
|
||||||
: "domain")
|
|
||||||
+ '("' + part.replace(/"/g, "%22").replace(/[*]$/, "") + '")')
|
|
||||||
.join(", ");
|
|
||||||
return namespace + "@-moz-document " + selectors + "{\n" + css + "\n}\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
let queryinterface = XPCOMUtils.generateQI([Components.interfaces.nsIConsoleListener]);
|
|
||||||
/* What happens if more than one thread tries to use this? */
|
|
||||||
let testDoc = document.implementation.createDocument(XHTML, "doc", null);
|
|
||||||
function checkSyntax(uri)
|
|
||||||
{
|
|
||||||
let errors = [];
|
|
||||||
let listener = {
|
|
||||||
QueryInterface: queryinterface,
|
|
||||||
observe: function (message)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
message = message.QueryInterface(Components.interfaces.nsIScriptError);
|
|
||||||
if (message.sourceName == uri)
|
|
||||||
errors.push(message);
|
|
||||||
}
|
|
||||||
catch (e) {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
consoleService.registerListener(listener);
|
|
||||||
if (testDoc.documentElement.firstChild)
|
|
||||||
testDoc.documentElement.removeChild(testDoc.documentElement.firstChild);
|
|
||||||
testDoc.documentElement.appendChild(util.xmlToDom(
|
|
||||||
<html><head><link type="text/css" rel="stylesheet" href={uri}/></head></html>, testDoc));
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Throws NS_ERROR_DOM_INVALID_ACCESS_ERR if not finished loading
|
|
||||||
testDoc.styleSheets[0].cssRules.length;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (e)
|
|
||||||
{
|
|
||||||
if (e.name != "NS_ERROR_DOM_INVALID_ACCESS_ERR")
|
|
||||||
return [e.toString()];
|
|
||||||
sleep(10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
consoleService.unregisterListener(listener);
|
|
||||||
}
|
|
||||||
if (errors.length)
|
|
||||||
{
|
|
||||||
let err = new Error("", errors[0].sourceName.replace(/^(chrome-data:text\/css,).*/, "$1..."), errors[0].lineNumber);
|
|
||||||
err.name = "CSSError"
|
|
||||||
err.message = errors.reduce(function (msg, e) msg + "; " + e.lineNumber + ": " + e.errorMessage, errors.shift().errorMessage);
|
|
||||||
err.echoerr = err.fileName + ":" + err.lineNumber + ": " + err.message;
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Styles.prototype = {
|
|
||||||
get sites() util.Array.uniq(util.Array.flatten([v.sites for ([k, v] in this.userSheets)]))
|
|
||||||
};
|
|
||||||
|
|
||||||
let styles = storage.newObject("styles", Styles, false);
|
|
||||||
|
|
||||||
/* FIXME: This doesn't belong here. */
|
/* FIXME: This doesn't belong here. */
|
||||||
let mainWindowID = config.mainWindowID || "main-window";
|
let mainWindowID = config.mainWindowID || "main-window";
|
||||||
let fontSize = util.computedStyle(document.getElementById(mainWindowID))["font-size"];
|
let fontSize = util.computedStyle(document.getElementById(mainWindowID))["font-size"];
|
||||||
@@ -813,114 +576,6 @@ function Buffer() //{{{
|
|||||||
function () { BrowserStop(); },
|
function () { BrowserStop(); },
|
||||||
{ argCount: "0" });
|
{ argCount: "0" });
|
||||||
|
|
||||||
commands.add(["sty[le]"],
|
|
||||||
"Add or list user styles",
|
|
||||||
function (args, special)
|
|
||||||
{
|
|
||||||
let [filter] = args.arguments;
|
|
||||||
let name = args["-name"];
|
|
||||||
let css = args.literalArg;
|
|
||||||
|
|
||||||
if (!css)
|
|
||||||
{
|
|
||||||
let list = Array.concat([i for (i in styles.userNames)],
|
|
||||||
[i for (i in styles.userSheets) if (!i[1].ref.length)]);
|
|
||||||
let str = template.tabular(["", "Filter", "CSS"],
|
|
||||||
["padding: 0 1em 0 1ex; vertical-align: top", "padding: 0 1em 0 0; vertical-align: top"],
|
|
||||||
([k, v[1].join(","), v[2]]
|
|
||||||
for ([i, [k, v]] in Iterator(list))
|
|
||||||
if ((!filter || v[1].indexOf(filter) >= 0) && (!name || v[0] == name))));
|
|
||||||
commandline.echo(str, commandline.HL_NORMAL, commandline.FORCE_MULTILINE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
let err = styles.addSheet(name, filter, css, false, special);
|
|
||||||
if (err)
|
|
||||||
liberator.echoerr(err);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
completer: function (filter) {
|
|
||||||
let compl = [];
|
|
||||||
try
|
|
||||||
{
|
|
||||||
compl.push([content.location.host, "Current Host"]);
|
|
||||||
compl.push([content.location.href, "Current URL"]);
|
|
||||||
}
|
|
||||||
catch (e) {}
|
|
||||||
comp = compl.concat([[s, ""] for each (s in styles.sites)])
|
|
||||||
return [0, completion.filter(compl, filter)];
|
|
||||||
},
|
|
||||||
argCount: 1,
|
|
||||||
bang: true,
|
|
||||||
hereDoc: true,
|
|
||||||
literal: true,
|
|
||||||
options: [[["-name", "-n"], commands.OPTION_STRING]],
|
|
||||||
serial: function () [
|
|
||||||
{
|
|
||||||
command: this.name,
|
|
||||||
bang: true,
|
|
||||||
options: sty.name ? {"-name": sty.name} : {},
|
|
||||||
arguments: [sty.sites.join(",")],
|
|
||||||
literalArg: sty.css
|
|
||||||
} for ([k, sty] in styles.userSheets)
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
commands.add(["dels[tyle]"],
|
|
||||||
"Remove a user stylesheet",
|
|
||||||
function (args) {
|
|
||||||
styles.removeSheet(args["-name"], args.arguments[0], args.literalArg, args["-index"], false);
|
|
||||||
},
|
|
||||||
{
|
|
||||||
argCount: 1,
|
|
||||||
completer: function (filter) [0, completion.filter(
|
|
||||||
[[i, <>{s.sites.join(",")}: {s.css.replace("\n", "\\n")}</>]
|
|
||||||
for ([i, s] in styles.userSheets)
|
|
||||||
]
|
|
||||||
.concat([[s, ""] for each (s in styles.sites)])
|
|
||||||
, filter)],
|
|
||||||
literal: true,
|
|
||||||
options: [[["-index", "-i"], commands.OPTION_INT],
|
|
||||||
[["-name", "-n"], commands.OPTION_STRING]]
|
|
||||||
});
|
|
||||||
|
|
||||||
commands.add(["hi[ghlight]"],
|
|
||||||
"Set the style of certain display elements",
|
|
||||||
function (args, special)
|
|
||||||
{
|
|
||||||
let key = args.arguments[0];
|
|
||||||
let css = args.literalArg;
|
|
||||||
if (!css && !(key && special))
|
|
||||||
{
|
|
||||||
let str = template.tabular(["Key", "CSS"],
|
|
||||||
["padding: 0 1em 0 0; vertical-align: top"],
|
|
||||||
(h for (h in highlight) if (!key || h[0].indexOf(key) > -1)));
|
|
||||||
commandline.echo(str, commandline.HL_NORMAL, commandline.FORCE_MULTILINE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
buffer.highlight(key, css, special);
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// TODO: add this as a standard highlight completion function?
|
|
||||||
// I agree. It could (should) be much more sophisticated. --Kris
|
|
||||||
completer: function (filter) [0,
|
|
||||||
completion.filter([[v instanceof Array ? v[0] : v, ""] for ([k, v] in Iterator(highlightClasses))], filter)
|
|
||||||
],
|
|
||||||
argCount: 1,
|
|
||||||
bang: true,
|
|
||||||
hereDoc: true,
|
|
||||||
literal: true,
|
|
||||||
serial: function () [
|
|
||||||
{
|
|
||||||
command: this.name,
|
|
||||||
arguments: [k],
|
|
||||||
literalArg: v
|
|
||||||
}
|
|
||||||
for ([k, v] in Iterator(highlight))
|
|
||||||
]
|
|
||||||
});
|
|
||||||
|
|
||||||
commands.add(["vie[wsource]"],
|
commands.add(["vie[wsource]"],
|
||||||
"View source code of current document",
|
"View source code of current document",
|
||||||
function (args, special) { buffer.viewSource(args.arguments[0], special); },
|
function (args, special) { buffer.viewSource(args.arguments[0], special); },
|
||||||
@@ -1030,7 +685,7 @@ function Buffer() //{{{
|
|||||||
// put feeds rss into pageFeeds[]
|
// put feeds rss into pageFeeds[]
|
||||||
let nFeed = 0;
|
let nFeed = 0;
|
||||||
var linkNodes = doc.getElementsByTagName("link");
|
var linkNodes = doc.getElementsByTagName("link");
|
||||||
for (link in arrayIter(linkNodes))
|
for (link in util.arrayIter(linkNodes))
|
||||||
{
|
{
|
||||||
if (!link.href)
|
if (!link.href)
|
||||||
return;
|
return;
|
||||||
@@ -1065,7 +720,7 @@ function Buffer() //{{{
|
|||||||
.getService(nsICacheService);
|
.getService(nsICacheService);
|
||||||
let cacheKey = doc.location.toString().replace(/#.*$/, "");
|
let cacheKey = doc.location.toString().replace(/#.*$/, "");
|
||||||
|
|
||||||
for (let proto in arrayIter(["HTTP", "FTP"]))
|
for (let proto in util.arrayIter(["HTTP", "FTP"]))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1206,39 +861,6 @@ function Buffer() //{{{
|
|||||||
|
|
||||||
addPageInfoSection: addPageInfoSection,
|
addPageInfoSection: addPageInfoSection,
|
||||||
|
|
||||||
highlight: function (key, style, force)
|
|
||||||
{
|
|
||||||
let [, class, selectors] = key.match(/^([a-zA-Z_-]+)(.*)/);
|
|
||||||
|
|
||||||
class = highlightClasses.filter(function (i) i == class || i[0] == class)[0];
|
|
||||||
if (!class)
|
|
||||||
{
|
|
||||||
liberator.echoerr("Unknown highlight keyword");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!(class instanceof Array))
|
|
||||||
class = [class];
|
|
||||||
|
|
||||||
styles.removeSheet("hl-" + key, null, null, null, true);
|
|
||||||
highlight.remove(key);
|
|
||||||
|
|
||||||
if (/^\s*$/.test(style))
|
|
||||||
return;
|
|
||||||
|
|
||||||
let cssClass = class[1] || ".hl-" + class[0];
|
|
||||||
let scope = class[2] || highlightDocs;
|
|
||||||
|
|
||||||
let css = style.replace(/(?:!\s*important\s*)?(?:;?\s*$|;)/g, "!important;")
|
|
||||||
.replace(";!important;", ";", "g") // Seeming Spidermonkey bug
|
|
||||||
css = cssClass + selectors + " { " + css + " }";
|
|
||||||
|
|
||||||
let error = styles.addSheet("hl-" + key, scope, css, true, force);
|
|
||||||
if (error)
|
|
||||||
liberator.echoerr(error);
|
|
||||||
else
|
|
||||||
highlight.set(key, style);
|
|
||||||
},
|
|
||||||
|
|
||||||
// returns an XPathResult object
|
// returns an XPathResult object
|
||||||
evaluateXPath: function (expression, doc, elem, asIterator)
|
evaluateXPath: function (expression, doc, elem, asIterator)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ function Search() //{{{
|
|||||||
|
|
||||||
if (!aWord)
|
if (!aWord)
|
||||||
{
|
{
|
||||||
let elems = doc.getElementsByClassName("__liberator-search");
|
let elems = doc.getElementsByClassName("liberator-search");
|
||||||
for (let i = elems.length; --i >= 0;)
|
for (let i = elems.length; --i >= 0;)
|
||||||
{
|
{
|
||||||
let elem = elems[i];
|
let elem = elems[i];
|
||||||
@@ -303,7 +303,7 @@ function Search() //{{{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var baseNode = <span class="__liberator-search"/>
|
var baseNode = <span class="liberator-search"/>
|
||||||
baseNode = util.xmlToDom(baseNode, window.content.document);
|
baseNode = util.xmlToDom(baseNode, window.content.document);
|
||||||
|
|
||||||
var body = doc.body;
|
var body = doc.body;
|
||||||
@@ -551,7 +551,7 @@ function Search() //{{{
|
|||||||
highlight: function (text)
|
highlight: function (text)
|
||||||
{
|
{
|
||||||
// already highlighted?
|
// already highlighted?
|
||||||
if (window.content.document.getElementsByClassName("__liberator-search").length > 0)
|
if (window.content.document.getElementsByClassName("liberator-search").length > 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!text)
|
if (!text)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
["liberator.js",
|
["liberator.js",
|
||||||
"util.js",
|
"util.js",
|
||||||
|
"style.js",
|
||||||
"config.js",
|
"config.js",
|
||||||
"buffer.js",
|
"buffer.js",
|
||||||
"commands.js",
|
"commands.js",
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ const liberator = (function () //{{{
|
|||||||
|
|
||||||
var callbacks = [];
|
var callbacks = [];
|
||||||
var observers = [];
|
var observers = [];
|
||||||
|
function registerObserver(type, callback)
|
||||||
|
{
|
||||||
|
observers.push([type, callback]);
|
||||||
|
}
|
||||||
|
|
||||||
function loadModule(name, func)
|
function loadModule(name, func)
|
||||||
{
|
{
|
||||||
@@ -46,6 +50,7 @@ const liberator = (function () //{{{
|
|||||||
liberator.log(message, 0);
|
liberator.log(message, 0);
|
||||||
liberator.dump(message);
|
liberator.dump(message);
|
||||||
modules[name] = func();
|
modules[name] = func();
|
||||||
|
liberator.triggerObserver("load_" + name, name);
|
||||||
}
|
}
|
||||||
catch (e)
|
catch (e)
|
||||||
{
|
{
|
||||||
@@ -57,7 +62,7 @@ const liberator = (function () //{{{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only general options are added here, which are valid for all vimperator like extensions
|
// Only general options are added here, which are valid for all vimperator like extensions
|
||||||
function addOptions()
|
registerObserver("load_options", function ()
|
||||||
{
|
{
|
||||||
options.add(["errorbells", "eb"],
|
options.add(["errorbells", "eb"],
|
||||||
"Ring the bell when an error message is displayed",
|
"Ring the bell when an error message is displayed",
|
||||||
@@ -140,9 +145,9 @@ const liberator = (function () //{{{
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
})
|
||||||
|
|
||||||
function addMappings()
|
registerObserver("load_mappings", function ()
|
||||||
{
|
{
|
||||||
mappings.add(modes.all, ["<F1>"],
|
mappings.add(modes.all, ["<F1>"],
|
||||||
"Open help window",
|
"Open help window",
|
||||||
@@ -158,9 +163,9 @@ const liberator = (function () //{{{
|
|||||||
mappings.add([modes.NORMAL], ["ZZ"],
|
mappings.add([modes.NORMAL], ["ZZ"],
|
||||||
"Quit and save the session",
|
"Quit and save the session",
|
||||||
function () { liberator.quit(true); });
|
function () { liberator.quit(true); });
|
||||||
}
|
})
|
||||||
|
|
||||||
function addCommands()
|
registerObserver("load_commands", function ()
|
||||||
{
|
{
|
||||||
commands.add(["addo[ns]"],
|
commands.add(["addo[ns]"],
|
||||||
"Manage available Extensions and Themes",
|
"Manage available Extensions and Themes",
|
||||||
@@ -529,7 +534,7 @@ const liberator = (function () //{{{
|
|||||||
argCount: "0",
|
argCount: "0",
|
||||||
bang: true
|
bang: true
|
||||||
});
|
});
|
||||||
}
|
})
|
||||||
|
|
||||||
// initially hide all GUI, it is later restored unless the user has :set go= or something
|
// initially hide all GUI, it is later restored unless the user has :set go= or something
|
||||||
// similar in his config
|
// similar in his config
|
||||||
@@ -603,10 +608,7 @@ const liberator = (function () //{{{
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
registerObserver: function (type, callback)
|
registerObserver: registerObserver,
|
||||||
{
|
|
||||||
observers.push([type, callback]);
|
|
||||||
},
|
|
||||||
|
|
||||||
triggerObserver: function (type, data)
|
triggerObserver: function (type, data)
|
||||||
{
|
{
|
||||||
@@ -1145,9 +1147,9 @@ const liberator = (function () //{{{
|
|||||||
config.features.push(navigator.platform);
|
config.features.push(navigator.platform);
|
||||||
|
|
||||||
// commands must always be the first module to be initialized
|
// commands must always be the first module to be initialized
|
||||||
loadModule("commands", Commands); addCommands();
|
loadModule("commands", Commands);
|
||||||
loadModule("options", Options); addOptions();
|
loadModule("options", Options);
|
||||||
loadModule("mappings", Mappings); addMappings();
|
loadModule("mappings", Mappings);
|
||||||
loadModule("buffer", Buffer);
|
loadModule("buffer", Buffer);
|
||||||
loadModule("events", Events);
|
loadModule("events", Events);
|
||||||
loadModule("commandline", CommandLine);
|
loadModule("commandline", CommandLine);
|
||||||
|
|||||||
473
content/style.js
Normal file
473
content/style.js
Normal file
@@ -0,0 +1,473 @@
|
|||||||
|
/***** BEGIN LICENSE BLOCK ***** {{{
|
||||||
|
©2008 Kris Maglione <maglione.k at Gmail>
|
||||||
|
Distributable under the terms of the MIT license, which allows
|
||||||
|
for sublicensing under any compatible license, including the MPL,
|
||||||
|
GPL, and MPL. Anyone who changes this file is welcome to relicense
|
||||||
|
it under any or all of those licenseses.
|
||||||
|
}}} ***** END LICENSE BLOCK *****/
|
||||||
|
|
||||||
|
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
|
|
||||||
|
function Highlights(name, store, serial)
|
||||||
|
{
|
||||||
|
const highlightCSS = <![CDATA[
|
||||||
|
Boolean color: red;
|
||||||
|
Function color: navy;
|
||||||
|
Null color: blue;
|
||||||
|
Number color: blue;
|
||||||
|
Object color: maroon;
|
||||||
|
String color: green;
|
||||||
|
|
||||||
|
Normal color: black; background: white;
|
||||||
|
ErrorMsg color: white; background: red;
|
||||||
|
InfoMsg color: black; background: white;
|
||||||
|
ModeMsg color: white; background: white;
|
||||||
|
MoreMsg color: green; background: white;
|
||||||
|
WarningMsg color: red; background: white;
|
||||||
|
Message white-space: normal; min-width: 100%; padding-left: 2em; text-indent: -2em; display: block;
|
||||||
|
|
||||||
|
Filter font-weight: bold;
|
||||||
|
|
||||||
|
Keyword color: red;
|
||||||
|
Tag color: blue;
|
||||||
|
|
||||||
|
LineNr color: orange; background: white;
|
||||||
|
Question color: green; background: white;
|
||||||
|
|
||||||
|
StatusLine color: white; background: black;
|
||||||
|
StatusLineBroken color: black; background: #FF6060; /* light-red */
|
||||||
|
StatusLineSecure color: black; background: #B0FF00; /* light-green */
|
||||||
|
|
||||||
|
TabClose
|
||||||
|
TabIcon
|
||||||
|
TabText
|
||||||
|
TabNumber font-weight: bold; margin: 0px; padding-right: .3ex;
|
||||||
|
TabIconNumber {
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: black -1px 0 1px, black 0 1px 1px, black 1px 0 1px, black 0 -1px 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
Title color: magenta; background: white; font-weight: bold;
|
||||||
|
URL text-decoration: none; color: green; background: inherit;
|
||||||
|
URL:hover text-decoration: underline; cursor: pointer;
|
||||||
|
|
||||||
|
Bell,#liberator-visualbell border: none; background-color: black;
|
||||||
|
Hint,.liberator-hint,* {
|
||||||
|
z-index: 5000;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
background-color: red;
|
||||||
|
border-color: ButtonShadow;
|
||||||
|
border-width: 0px;
|
||||||
|
border-style: solid;
|
||||||
|
padding: 0px 1px 0px 1px;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
Search,.liberator-search,* {
|
||||||
|
display: inline;
|
||||||
|
font-size: inherit;
|
||||||
|
padding: 0;
|
||||||
|
color: black;
|
||||||
|
background-color: yellow;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
]]>.toString();
|
||||||
|
var self = this;
|
||||||
|
var highlight = {};
|
||||||
|
var styles = storage.styles;
|
||||||
|
|
||||||
|
const Highlight = Struct("class", "selector", "filter", "default", "value");
|
||||||
|
Highlight.defaultValue("filter", function () "chrome://liberator/content/buffer.xhtml,chrome://browser/content/browser.xul");
|
||||||
|
Highlight.defaultValue("selector", function () ".hl-" + this.class);
|
||||||
|
Highlight.defaultValue("value", function () this.default);
|
||||||
|
Highlight.prototype.toString = function () [k + ": " + util.escapeString(v || "undefined") for ([k, v] in this)].join(", ");
|
||||||
|
|
||||||
|
this.__iterator__ = function () (v for ([k,v] in Iterator(highlight)));
|
||||||
|
|
||||||
|
this.get = function (k) highlight[k];
|
||||||
|
this.set = function (key, newStyle, force)
|
||||||
|
{
|
||||||
|
let [, class, selectors] = key.match(/^([a-zA-Z_-]+)(.*)/);
|
||||||
|
|
||||||
|
if (!(class in highlight))
|
||||||
|
return "Unknown highlight keyword";
|
||||||
|
|
||||||
|
if (/^\s*$/.test(newStyle))
|
||||||
|
newStyle = null;
|
||||||
|
|
||||||
|
let style = highlight[key] || new Highlight(key);
|
||||||
|
styles.removeSheet(style.selector, null, null, true);
|
||||||
|
|
||||||
|
if (newStyle == null)
|
||||||
|
{
|
||||||
|
if (style.default == null)
|
||||||
|
{
|
||||||
|
delete highlight[style.class];
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
newStyle = style.default;
|
||||||
|
force = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let css = newStyle.replace(/(?:!\s*important\s*)?(?:;?\s*$|;)/g, "!important;")
|
||||||
|
.replace(";!important;", ";", "g"); // Seeming Spidermonkey bug
|
||||||
|
css = style.selector + " { " + css + " }";
|
||||||
|
|
||||||
|
let error = styles.addSheet(style.selector, style.filter, css, true, force);
|
||||||
|
if (!error)
|
||||||
|
style.value = newStyle;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
highlightCSS.replace(/\{((?:.|\n)*?)\}/g, function (_, _1) _1.replace(/\n\s*/g, " "))
|
||||||
|
.split("\n").filter(function (s) /\S/.test(s))
|
||||||
|
.forEach(function (style)
|
||||||
|
{
|
||||||
|
let style = Highlight.apply(Highlight, Array.slice(style.match(/^\s*([^,\s]+)(?:,([^,\s]+))?(?:,([^,\s]+))?(?:\s+(.*))?/), 1));
|
||||||
|
highlight[style.class] = style;
|
||||||
|
self.set(style.class);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function Styles(name, store, serial)
|
||||||
|
{
|
||||||
|
/* Can't reference liberator or Components inside Styles --
|
||||||
|
* they're members of the window object, which disappear
|
||||||
|
* with this window.
|
||||||
|
*/
|
||||||
|
const util = modules.util;
|
||||||
|
const sleep = liberator.sleep;
|
||||||
|
const storage = modules.storage;
|
||||||
|
const consoleService = Components.classes["@mozilla.org/consoleservice;1"]
|
||||||
|
.getService(Components.interfaces.nsIConsoleService);
|
||||||
|
const ios = Components.classes["@mozilla.org/network/io-service;1"]
|
||||||
|
.getService(Components.interfaces.nsIIOService);
|
||||||
|
const sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
|
||||||
|
.getService(Components.interfaces.nsIStyleSheetService);
|
||||||
|
const XHTML = "http://www.w3.org/1999/xhtml";
|
||||||
|
const namespace = "@namespace html url(" + XHTML + ");\n" +
|
||||||
|
"@namespace xul url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);\n";
|
||||||
|
const Sheet = new Struct("name", "sites", "css", "ref");
|
||||||
|
|
||||||
|
let cssUri = function (css) "chrome-data:text/css," + encodeURI(css);
|
||||||
|
|
||||||
|
let userSheets = [];
|
||||||
|
let systemSheets = [];
|
||||||
|
let userNames = {};
|
||||||
|
let systemNames = {};
|
||||||
|
|
||||||
|
this.__iterator__ = function () Iterator(userSheets.concat(systemSheets));
|
||||||
|
this.__defineGetter__("systemSheets", function () Iterator(systemSheets));
|
||||||
|
this.__defineGetter__("userSheets", function () Iterator(userSheets));
|
||||||
|
this.__defineGetter__("systemNames", function () Iterator(systemNames));
|
||||||
|
this.__defineGetter__("userNames", function () Iterator(userNames));
|
||||||
|
|
||||||
|
this.addSheet = function (name, filter, css, system, force)
|
||||||
|
{
|
||||||
|
let sheets = system ? systemSheets : userSheets;
|
||||||
|
let names = system ? systemNames : userNames;
|
||||||
|
if (name && name in names)
|
||||||
|
this.removeSheet(name, null, null, null, system);
|
||||||
|
|
||||||
|
let sheet = sheets.filter(function (s) s.sites.join(",") == filter && s.css == css)[0];
|
||||||
|
if (!sheet)
|
||||||
|
sheet = new Sheet(name, filter.split(","), css, null);
|
||||||
|
|
||||||
|
if (sheet.ref == null) // Not registered yet
|
||||||
|
{
|
||||||
|
sheet.ref = [];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.registerSheet(cssUri(wrapCSS(sheet)), !force);
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
return e.echoerr || e;
|
||||||
|
}
|
||||||
|
sheets.push(sheet);
|
||||||
|
}
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
sheet.ref.push(name);
|
||||||
|
names[name] = sheet;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.findSheets = function (name, filter, css, index, system)
|
||||||
|
{
|
||||||
|
let sheets = system ? systemSheets : userSheets;
|
||||||
|
let names = system ? systemNames : userNames;
|
||||||
|
|
||||||
|
// Grossly inefficient.
|
||||||
|
let matches = [k for ([k, v] in sheets)];
|
||||||
|
if (index)
|
||||||
|
matches = String(index).split(",").filter(function (i) i in sheets);
|
||||||
|
if (name)
|
||||||
|
matches = matches.filter(function (i) sheets[i] == names[name]);
|
||||||
|
if (css)
|
||||||
|
matches = matches.filter(function (i) sheets[i].css == css);
|
||||||
|
if (filter)
|
||||||
|
matches = matches.filter(function (i) sheets[i].sites.indexOf(filter) >= 0);
|
||||||
|
return matches;
|
||||||
|
},
|
||||||
|
|
||||||
|
this.removeSheet = function (name, filter, css, index, system)
|
||||||
|
{
|
||||||
|
let self = this;
|
||||||
|
let sheets = system ? systemSheets : userSheets;
|
||||||
|
let names = system ? systemNames : userNames;
|
||||||
|
|
||||||
|
if (filter && filter.indexOf(",") > -1)
|
||||||
|
return filter.split(",").reduce(
|
||||||
|
function (n, f) n + self.removeSheet(name, f, index, system), 0);
|
||||||
|
|
||||||
|
if (filter == undefined)
|
||||||
|
filter = "";
|
||||||
|
|
||||||
|
let matches = this.findSheets(name, filter, css, index, system);
|
||||||
|
if (matches.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (let [,i] in Iterator(matches.reverse()))
|
||||||
|
{
|
||||||
|
let sheet = sheets[i];
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
sheet.ref.splice(sheet.ref.indexOf(name));
|
||||||
|
delete names[name];
|
||||||
|
}
|
||||||
|
if (!sheet.ref.length)
|
||||||
|
{
|
||||||
|
sheets.splice(i);
|
||||||
|
this.unregisterSheet(cssUri(wrapCSS(sheet)));
|
||||||
|
}
|
||||||
|
// Filter out the given site, and re-add if there are any left
|
||||||
|
if (filter)
|
||||||
|
{
|
||||||
|
let sites = sheet.sites.filter(function (f) f != filter);
|
||||||
|
if (sites.length)
|
||||||
|
this.addSheet(name, sites.join(","), css, system, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.registerSheet = function (uri, doCheckSyntax, reload)
|
||||||
|
{
|
||||||
|
if (doCheckSyntax)
|
||||||
|
checkSyntax(uri);
|
||||||
|
if (reload)
|
||||||
|
this.unregisterSheet(uri);
|
||||||
|
uri = ios.newURI(uri, null, null);
|
||||||
|
if (reload || !sss.sheetRegistered(uri, sss.USER_SHEET))
|
||||||
|
sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.unregisterSheet = function (uri)
|
||||||
|
{
|
||||||
|
uri = ios.newURI(uri, null, null);
|
||||||
|
if (sss.sheetRegistered(uri, sss.USER_SHEET))
|
||||||
|
sss.unregisterSheet(uri, sss.USER_SHEET);
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrapCSS(sheet)
|
||||||
|
{
|
||||||
|
let filter = sheet.sites;
|
||||||
|
let css = sheet.css;
|
||||||
|
if (filter[0] == "*")
|
||||||
|
return namespace + css;
|
||||||
|
let selectors = filter.map(function (part) (/[*]$/.test(part) ? "url-prefix" :
|
||||||
|
/[\/:]/.test(part) ? "url"
|
||||||
|
: "domain")
|
||||||
|
+ '("' + part.replace(/"/g, "%22").replace(/[*]$/, "") + '")')
|
||||||
|
.join(", ");
|
||||||
|
return namespace + "@-moz-document " + selectors + "{\n" + css + "\n}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
let queryinterface = XPCOMUtils.generateQI([Components.interfaces.nsIConsoleListener]);
|
||||||
|
/* What happens if more than one thread tries to use this? */
|
||||||
|
let testDoc = document.implementation.createDocument(XHTML, "doc", null);
|
||||||
|
function checkSyntax(uri)
|
||||||
|
{
|
||||||
|
let errors = [];
|
||||||
|
let listener = {
|
||||||
|
QueryInterface: queryinterface,
|
||||||
|
observe: function (message)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
message = message.QueryInterface(Components.interfaces.nsIScriptError);
|
||||||
|
if (message.sourceName == uri)
|
||||||
|
errors.push(message);
|
||||||
|
}
|
||||||
|
catch (e) {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
consoleService.registerListener(listener);
|
||||||
|
if (testDoc.documentElement.firstChild)
|
||||||
|
testDoc.documentElement.removeChild(testDoc.documentElement.firstChild);
|
||||||
|
testDoc.documentElement.appendChild(util.xmlToDom(
|
||||||
|
<html><head><link type="text/css" rel="stylesheet" href={uri}/></head></html>, testDoc));
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Throws NS_ERROR_DOM_INVALID_ACCESS_ERR if not finished loading
|
||||||
|
testDoc.styleSheets[0].cssRules.length;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (e)
|
||||||
|
{
|
||||||
|
if (e.name != "NS_ERROR_DOM_INVALID_ACCESS_ERR")
|
||||||
|
return [e.toString()];
|
||||||
|
sleep(10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
consoleService.unregisterListener(listener);
|
||||||
|
}
|
||||||
|
if (errors.length)
|
||||||
|
{
|
||||||
|
let err = new Error("", errors[0].sourceName.replace(/^(chrome-data:text\/css,).*/, "$1..."), errors[0].lineNumber);
|
||||||
|
err.name = "CSSError"
|
||||||
|
err.message = errors.reduce(function (msg, e) msg + "; " + e.lineNumber + ": " + e.errorMessage,
|
||||||
|
errors.shift().errorMessage);
|
||||||
|
err.echoerr = err.fileName + ":" + err.lineNumber + ": " + err.message;
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Styles.prototype = {
|
||||||
|
get sites() util.Array.uniq(util.Array.flatten([v.sites for ([k, v] in this.userSheets)]))
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = storage.newObject("styles", Styles, false);
|
||||||
|
const highlight = storage.newObject("highlight", Highlights, false);
|
||||||
|
|
||||||
|
liberator.registerObserver("load_commands", function ()
|
||||||
|
{
|
||||||
|
commands.add(["sty[le]"],
|
||||||
|
"Add or list user styles",
|
||||||
|
function (args, special)
|
||||||
|
{
|
||||||
|
let [filter] = args.arguments;
|
||||||
|
let name = args["-name"];
|
||||||
|
let css = args.literalArg;
|
||||||
|
|
||||||
|
if (!css)
|
||||||
|
{
|
||||||
|
let list = Array.concat([i for (i in styles.userNames)],
|
||||||
|
[i for (i in styles.userSheets) if (!i[1].ref.length)]);
|
||||||
|
let str = template.tabular(["", "Filter", "CSS"],
|
||||||
|
["padding: 0 1em 0 1ex; vertical-align: top", "padding: 0 1em 0 0; vertical-align: top"],
|
||||||
|
([k, v[1].join(","), v[2]]
|
||||||
|
for ([i, [k, v]] in Iterator(list))
|
||||||
|
if ((!filter || v[1].indexOf(filter) >= 0) && (!name || v[0] == name))));
|
||||||
|
commandline.echo(str, commandline.HL_NORMAL, commandline.FORCE_MULTILINE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
let err = styles.addSheet(name, filter, css, false, special);
|
||||||
|
if (err)
|
||||||
|
liberator.echoerr(err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
completer: function (filter) {
|
||||||
|
let compl = [];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
compl.push([content.location.host, "Current Host"]);
|
||||||
|
compl.push([content.location.href, "Current URL"]);
|
||||||
|
}
|
||||||
|
catch (e) {}
|
||||||
|
comp = compl.concat([[s, ""] for each (s in styles.sites)])
|
||||||
|
return [0, completion.filter(compl, filter)];
|
||||||
|
},
|
||||||
|
argCount: 1,
|
||||||
|
bang: true,
|
||||||
|
hereDoc: true,
|
||||||
|
literal: true,
|
||||||
|
options: [[["-name", "-n"], commands.OPTION_STRING]],
|
||||||
|
serial: function () [
|
||||||
|
{
|
||||||
|
command: this.name,
|
||||||
|
bang: true,
|
||||||
|
options: sty.name ? {"-name": sty.name} : {},
|
||||||
|
arguments: [sty.sites.join(",")],
|
||||||
|
literalArg: sty.css
|
||||||
|
} for ([k, sty] in styles.userSheets)
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
commands.add(["dels[tyle]"],
|
||||||
|
"Remove a user stylesheet",
|
||||||
|
function (args) {
|
||||||
|
styles.removeSheet(args["-name"], args.arguments[0], args.literalArg, args["-index"], false);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
argCount: 1,
|
||||||
|
completer: function (filter) [0, completion.filter(
|
||||||
|
[[i, <>{s.sites.join(",")}: {s.css.replace("\n", "\\n")}</>]
|
||||||
|
for ([i, s] in styles.userSheets)
|
||||||
|
]
|
||||||
|
.concat([[s, ""] for each (s in styles.sites)])
|
||||||
|
, filter)],
|
||||||
|
literal: true,
|
||||||
|
options: [[["-index", "-i"], commands.OPTION_INT],
|
||||||
|
[["-name", "-n"], commands.OPTION_STRING]]
|
||||||
|
});
|
||||||
|
|
||||||
|
commands.add(["hi[ghlight]"],
|
||||||
|
"Set the style of certain display elements",
|
||||||
|
function (args, special)
|
||||||
|
{
|
||||||
|
let key = args.arguments[0];
|
||||||
|
let css = args.literalArg;
|
||||||
|
if (!css && !(key && special))
|
||||||
|
{
|
||||||
|
let str = template.tabular(["Key", "CSS"],
|
||||||
|
["padding: 0 1em 0 0; vertical-align: top"],
|
||||||
|
([h.class, h.value]
|
||||||
|
for (h in highlight)
|
||||||
|
if (!key || h.class.indexOf(key) > -1)));
|
||||||
|
commandline.echo(str, commandline.HL_NORMAL, commandline.FORCE_MULTILINE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let error = highlight.set(key, css, special);
|
||||||
|
if (error)
|
||||||
|
liberator.echoerr(error);
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// TODO: add this as a standard highlight completion function?
|
||||||
|
// I agree. It could (should) be much more sophisticated. --Kris
|
||||||
|
completer: function (filter) [0,
|
||||||
|
completion.filter([[v.class, ""] for (v in highlight)], filter)
|
||||||
|
],
|
||||||
|
argCount: 1,
|
||||||
|
bang: true,
|
||||||
|
hereDoc: true,
|
||||||
|
literal: true,
|
||||||
|
serial: function () [
|
||||||
|
{
|
||||||
|
command: this.name,
|
||||||
|
arguments: [k],
|
||||||
|
literalArg: v
|
||||||
|
}
|
||||||
|
for ([k, v] in Iterator(highlight))
|
||||||
|
if (v.value != v.default)
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
@@ -214,8 +214,10 @@ function CommandLine() //{{{
|
|||||||
.selection.getRangeAt(0)
|
.selection.getRangeAt(0)
|
||||||
.startContainer.parentNode
|
.startContainer.parentNode
|
||||||
.scrollWidth > commandWidget.inputField.scrollWidth)
|
.scrollWidth > commandWidget.inputField.scrollWidth)
|
||||||
// Yeah, the min-width is stupid. Somehow, it doesn't work otherwise.
|
{
|
||||||
setMultiline(<p style={"white-space: normal; min-width: " + commandWidget.inputField.scrollWidth + "px; width: 100%"}>{str}</p>, highlightGroup);
|
setCommand("");
|
||||||
|
setMultiline(<span class="hl-Message">{str}</span>, highlightGroup);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: extract CSS
|
// TODO: extract CSS
|
||||||
@@ -233,7 +235,7 @@ function CommandLine() //{{{
|
|||||||
* after interpolated data.
|
* after interpolated data.
|
||||||
*/
|
*/
|
||||||
XML.ignoreWhitespace = typeof str == "xml";
|
XML.ignoreWhitespace = typeof str == "xml";
|
||||||
var output = <div class={"ex-command-output " + highlightGroup}>{template.maybeXML(str)}</div>;
|
var output = <div class={"ex-command-output " + highlightGroup} style={"min-width: " + commandlineWidget.scrollWidth + "px"}>{template.maybeXML(str)}</div>;
|
||||||
XML.ignoreWhiteSpace = true;
|
XML.ignoreWhiteSpace = true;
|
||||||
|
|
||||||
lastMowOutput = output;
|
lastMowOutput = output;
|
||||||
@@ -267,7 +269,7 @@ function CommandLine() //{{{
|
|||||||
if (win.scrollY >= win.scrollMaxY)
|
if (win.scrollY >= win.scrollMaxY)
|
||||||
setLine("Press ENTER or type command to continue", commandline.HL_QUESTION, true);
|
setLine("Press ENTER or type command to continue", commandline.HL_QUESTION, true);
|
||||||
else
|
else
|
||||||
setLine("-- More --", commandline.HL_QUESTION, true);
|
setLine("-- More --", commandline.HL_MOREMSG, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -278,7 +280,7 @@ function CommandLine() //{{{
|
|||||||
win.focus();
|
win.focus();
|
||||||
|
|
||||||
startHints = false;
|
startHints = false;
|
||||||
modes.push(modes.COMMAND_LINE, modes.OUTPUT_MULTILINE);
|
modes.set(modes.COMMAND_LINE, modes.OUTPUT_MULTILINE);
|
||||||
}
|
}
|
||||||
|
|
||||||
function autosizeMultilineInputWidget()
|
function autosizeMultilineInputWidget()
|
||||||
@@ -532,7 +534,7 @@ function CommandLine() //{{{
|
|||||||
let list = <></>;
|
let list = <></>;
|
||||||
|
|
||||||
for (let [,message] in Iterator(messageHistory.messages))
|
for (let [,message] in Iterator(messageHistory.messages))
|
||||||
list += <div class={message.highlight}>{message.str}</div>;
|
list += <div class={message.highlight + " hl-Message"}>{message.str}</div>;
|
||||||
|
|
||||||
liberator.echo(list, commandline.FORCE_MULTILINE);
|
liberator.echo(list, commandline.FORCE_MULTILINE);
|
||||||
}
|
}
|
||||||
@@ -591,7 +593,7 @@ function CommandLine() //{{{
|
|||||||
historyIndex = UNINITIALIZED;
|
historyIndex = UNINITIALIZED;
|
||||||
completionIndex = UNINITIALIZED;
|
completionIndex = UNINITIALIZED;
|
||||||
|
|
||||||
modes.push(modes.COMMAND_LINE, currentExtendedMode);
|
modes.set(modes.COMMAND_LINE, currentExtendedMode);
|
||||||
setHighlightGroup(this.HL_NORMAL);
|
setHighlightGroup(this.HL_NORMAL);
|
||||||
setPrompt(currentPrompt);
|
setPrompt(currentPrompt);
|
||||||
setCommand(currentCommand);
|
setCommand(currentCommand);
|
||||||
|
|||||||
@@ -484,10 +484,23 @@ function Struct()
|
|||||||
{
|
{
|
||||||
let self = this instanceof arguments.callee ? this : new arguments.callee();
|
let self = this instanceof arguments.callee ? this : new arguments.callee();
|
||||||
for (let [k, v] in Iterator(Array.slice(arguments)))
|
for (let [k, v] in Iterator(Array.slice(arguments)))
|
||||||
self[k] = v;
|
{
|
||||||
|
if (v != undefined)
|
||||||
|
self[k] = v;
|
||||||
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
ConStructor.prototype = self;
|
ConStructor.prototype = self;
|
||||||
|
ConStructor.defaultValue = function (key, val)
|
||||||
|
{
|
||||||
|
let i = args.indexOf(key);
|
||||||
|
let _i = "_" + i;
|
||||||
|
ConStructor.prototype.__defineGetter__(i, val);
|
||||||
|
ConStructor.prototype.__defineSetter__(i, function (val) {
|
||||||
|
this.__defineGetter__(i, function () this[_i]);
|
||||||
|
this[_i] = val;
|
||||||
|
});
|
||||||
|
};
|
||||||
return self.constructor = ConStructor;
|
return self.constructor = ConStructor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,7 +510,11 @@ Struct.prototype = {
|
|||||||
return this.constructor.apply(null, this.slice());
|
return this.constructor.apply(null, this.slice());
|
||||||
},
|
},
|
||||||
// Iterator over our named members
|
// Iterator over our named members
|
||||||
__iterator__: function () ([v, this[v]] for ([k, v] in this.members))
|
__iterator__: function ()
|
||||||
|
{
|
||||||
|
let self = this;
|
||||||
|
return ([v, self[v]] for ([k, v] in Iterator(self.members)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add no-sideeffect array methods. Can't set new Array() as the prototype or
|
// Add no-sideeffect array methods. Can't set new Array() as the prototype or
|
||||||
|
|||||||
Reference in New Issue
Block a user