mirror of
https://github.com/gryf/pentadactyl-pm.git
synced 2025-12-23 13:22:28 +01:00
Add a Struct() type for things like Bookmarks and Styles
This commit is contained in:
@@ -43,8 +43,10 @@ liberator.Bookmarks = function () //{{{
|
||||
const faviconService = Components.classes["@mozilla.org/browser/favicon-service;1"]
|
||||
.getService(Components.interfaces.nsIFaviconService);
|
||||
|
||||
const Bookmark = new liberator.util.Struct("url", "title", "icon", "keyword", "tags", "id");
|
||||
const Keyword = new liberator.util.Struct("keyword", "title", "icon", "url");
|
||||
|
||||
const storage = liberator.storage;
|
||||
const properties = { url: 0, title: 1, keyword: 2, tags: 3, id: 4, icon: 5 };
|
||||
function Cache(name, store, serial)
|
||||
{
|
||||
const rootFolders = [bookmarksService.toolbarFolder, bookmarksService.bookmarksMenuFolder, bookmarksService.unfiledBookmarksFolder];
|
||||
@@ -57,7 +59,7 @@ liberator.Bookmarks = function () //{{{
|
||||
this.__defineGetter__("bookmarks", function () { this.load(); return bookmarks; });
|
||||
|
||||
this.__defineGetter__("keywords",
|
||||
function () [[k[2], k[1], k[0], k[5]] for each (k in self.bookmarks) if (k[2])]);
|
||||
function () [new Keyword(k.keyword, k.title, k.icon, k.url) for each (k in self.bookmarks) if (k.keyword)]);
|
||||
|
||||
this.__iterator__ = function () (val for each (val in self.bookmarks));
|
||||
|
||||
@@ -67,7 +69,7 @@ liberator.Bookmarks = function () //{{{
|
||||
let keyword = bookmarksService.getKeywordForBookmark(node.itemId);
|
||||
let tags = taggingService.getTagsForURI(uri, {}) || [];
|
||||
let icon = faviconService.getFaviconImageForPage(uri).spec;
|
||||
return bookmarks.push([node.uri, node.title, keyword, tags, node.itemId, icon]);
|
||||
return bookmarks.push(new Bookmark(node.uri, node.title, icon, keyword, tags, node.itemId));
|
||||
}
|
||||
|
||||
function readBookmark(id)
|
||||
@@ -82,7 +84,7 @@ liberator.Bookmarks = function () //{{{
|
||||
function deleteBookmark(id)
|
||||
{
|
||||
var length = bookmarks.length;
|
||||
bookmarks = bookmarks.filter(function (item) item[properties.id] != id);
|
||||
bookmarks = bookmarks.filter(function (item) item.id != id);
|
||||
return bookmarks.length < length;
|
||||
}
|
||||
|
||||
@@ -160,13 +162,13 @@ liberator.Bookmarks = function () //{{{
|
||||
if (isAnnotation)
|
||||
return;
|
||||
// liberator.dump("onItemChanged(" + itemId + ", " + property + ", " + value + ")\n");
|
||||
var bookmark = bookmarks.filter(function (item) item[properties.id] == itemId)[0];
|
||||
var bookmark = bookmarks.filter(function (item) item.id == itemId)[0];
|
||||
if (bookmark)
|
||||
{
|
||||
if (property == "tags")
|
||||
value = taggingService.getTagsForURI(ioService.newURI(bookmark[properties.url], null, null), {});
|
||||
if (property in properties)
|
||||
bookmark[properties[property]] = value;
|
||||
value = taggingService.getTagsForURI(ioService.newURI(bookmark.url, null, null), {});
|
||||
if (property in bookmark)
|
||||
bookmark[property] = value;
|
||||
storage.fireEvent(name, "change", itemId);
|
||||
}
|
||||
},
|
||||
@@ -184,12 +186,7 @@ liberator.Bookmarks = function () //{{{
|
||||
let bookmarkObserver = function (key, event, arg)
|
||||
{
|
||||
if (event == "add")
|
||||
{
|
||||
let args = {};
|
||||
for (let [k, v] in Iterator(properties))
|
||||
args[k] = arg[v];
|
||||
liberator.autocommands.trigger("BookmarkAdd", args);
|
||||
}
|
||||
liberator.autocommands.trigger("BookmarkAdd", arg);
|
||||
liberator.statusline.updateUrl();
|
||||
}
|
||||
|
||||
@@ -512,14 +509,15 @@ liberator.Bookmarks = function () //{{{
|
||||
}
|
||||
|
||||
if (openItems)
|
||||
return liberator.open([i[0] for each (i in items)], liberator.NEW_TAB);
|
||||
return liberator.open([i.url for each (i in items)], liberator.NEW_TAB);
|
||||
|
||||
let list = liberator.template.bookmarks("title", (
|
||||
{
|
||||
url: item[0],
|
||||
title: item[1],
|
||||
extra: [['keyword', item[2], "hl-Keyword"],
|
||||
['tags', item[3].join(', '), "hl-Tag"]].filter(function (i) i[1])
|
||||
url: item.url,
|
||||
title: item.title,
|
||||
extra: [['keyword', item.keyword, "hl-Keyword"],
|
||||
['tags', item.tags.join(', '), "hl-Tag"]
|
||||
].filter(function (i) i[1])
|
||||
} for each (item in items)));
|
||||
liberator.commandline.echo(list, liberator.commandline.HL_NORMAL, liberator.commandline.FORCE_MULTILINE);
|
||||
},
|
||||
@@ -566,7 +564,7 @@ liberator.History = function () //{{{
|
||||
var node = rootNode.getChild(i);
|
||||
// liberator.dump("History child " + node.itemId + ": " + node.title + " - " + node.type);
|
||||
if (node.type == node.RESULT_TYPE_URI) // just make sure it's a bookmark
|
||||
history.push([node.uri, node.title || "[No title]", getIcon(node.uri)]);
|
||||
history.push([node.url, node.title || "[No title]", getIcon(node.uri)]);
|
||||
}
|
||||
|
||||
// close a container after using it!
|
||||
|
||||
@@ -69,7 +69,7 @@ liberator.Buffer = function () //{{{
|
||||
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 NAME = 0, SITES = 1, CSS = 2, REF = 3;
|
||||
const Sheet = new util.Struct("name", "sites", "css", "ref");
|
||||
|
||||
let cssUri = function (css) "data:text/css," + encodeURI(css);
|
||||
|
||||
@@ -91,13 +91,13 @@ liberator.Buffer = function () //{{{
|
||||
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];
|
||||
let sheet = sheets.filter(function (s) s.sites.join(",") == filter && s.css == css)[0];
|
||||
if (!sheet)
|
||||
sheet = [name, filter.split(","), css, null];
|
||||
sheet = new Sheet(name, filter.split(","), css, null);
|
||||
|
||||
if (sheet[REF] == null) // Not registered yet
|
||||
if (sheet.ref == null) // Not registered yet
|
||||
{
|
||||
sheet[REF] = [];
|
||||
sheet.ref = [];
|
||||
try
|
||||
{
|
||||
this.registerSheet(cssUri(wrapCSS(sheet)), !force);
|
||||
@@ -110,7 +110,7 @@ liberator.Buffer = function () //{{{
|
||||
}
|
||||
if (name)
|
||||
{
|
||||
sheet[REF].push(name);
|
||||
sheet.ref.push(name);
|
||||
names[name] = sheet;
|
||||
}
|
||||
return null;
|
||||
@@ -128,9 +128,9 @@ liberator.Buffer = function () //{{{
|
||||
if (name)
|
||||
matches = matches.filter(function (i) sheets[i] == names[name]);
|
||||
if (css)
|
||||
matches = matches.filter(function (i) sheets[i][CSS] == css);
|
||||
matches = matches.filter(function (i) sheets[i].css == css);
|
||||
if (filter)
|
||||
matches = matches.filter(function (i) sheets[i][SITES].indexOf(filter) >= 0);
|
||||
matches = matches.filter(function (i) sheets[i].sites.indexOf(filter) >= 0);
|
||||
return matches;
|
||||
},
|
||||
|
||||
@@ -156,10 +156,10 @@ liberator.Buffer = function () //{{{
|
||||
let sheet = sheets[i];
|
||||
if (name)
|
||||
{
|
||||
sheet[REF].splice(sheet[REF].indexOf(name));
|
||||
sheet.ref.splice(sheet.ref.indexOf(name));
|
||||
delete names[name];
|
||||
}
|
||||
if (!sheet[REF].length)
|
||||
if (!sheet.ref.length)
|
||||
{
|
||||
sheets.splice(i);
|
||||
this.unregisterSheet(cssUri(wrapCSS(sheet)));
|
||||
@@ -167,7 +167,7 @@ liberator.Buffer = function () //{{{
|
||||
// Filter out the given site, and re-add if there are any left
|
||||
if (filter)
|
||||
{
|
||||
let sites = sheet[SITES].filter(function (f) f != filter);
|
||||
let sites = sheet.sites.filter(function (f) f != filter);
|
||||
if (sites.length)
|
||||
this.addSheet(name, sites.join(","), css, system, true);
|
||||
}
|
||||
@@ -195,8 +195,8 @@ liberator.Buffer = function () //{{{
|
||||
|
||||
function wrapCSS(sheet)
|
||||
{
|
||||
let filter = sheet[SITES];
|
||||
let css = sheet[CSS];
|
||||
let filter = sheet.sites;
|
||||
let css = sheet.css;
|
||||
if (filter[0] == "*")
|
||||
return namespace + css;
|
||||
let selectors = filter.map(function (part) (/[*]$/.test(part) ? "url-prefix" :
|
||||
@@ -266,7 +266,7 @@ liberator.Buffer = function () //{{{
|
||||
}
|
||||
}
|
||||
Styles.prototype = {
|
||||
get sites() util.uniq(util.flatten([v[1] for ([k, v] in this.userSheets)])),
|
||||
get sites() util.uniq(util.flatten([v.sites for ([k, v] in this.userSheets)])),
|
||||
};
|
||||
|
||||
let styles = liberator.storage.newObject("styles", Styles, false);
|
||||
@@ -829,7 +829,7 @@ liberator.Buffer = function () //{{{
|
||||
if (!css)
|
||||
{
|
||||
let list = Array.concat([i for (i in styles.userNames)],
|
||||
[i for (i in styles.userSheets) if (!i[1][3].length)]);
|
||||
[i for (i in styles.userSheets) if (!i[1].ref.length)]);
|
||||
let str = liberator.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]]
|
||||
@@ -871,8 +871,10 @@ liberator.Buffer = function () //{{{
|
||||
{
|
||||
argCount: 1,
|
||||
completer: function (filter) [0, liberator.completion.filter(
|
||||
[[i, <>{s[1].join(",")}: {s[2].replace("\n", "\\n")}</>] for ([i, s] in styles.userSheets)]
|
||||
.concat([[s, ""] for each (s in styles.sites)])
|
||||
[[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"], liberator.commands.OPTION_INT],
|
||||
|
||||
@@ -186,6 +186,26 @@ liberator.Commands = function () //{{{
|
||||
return matches;
|
||||
}
|
||||
|
||||
function parseBool(arg)
|
||||
{
|
||||
if (arg == "true" || arg == "1" || arg == "on")
|
||||
return true;
|
||||
if (arg == "false" || arg == "0" || arg == "off")
|
||||
return false;
|
||||
return NaN;
|
||||
}
|
||||
|
||||
const ArgType = new liberator.util.Struct("description", "parse");
|
||||
const argTypes = [
|
||||
null,
|
||||
["no arg", function (arg) !arg],
|
||||
["boolean", parseBool],
|
||||
["string", function (val) val],
|
||||
["int", parseInt],
|
||||
["float", parseFloat],
|
||||
["list", function (arg) arg && arg.split(/\s*,\s*/)]
|
||||
].map(function (x) x && ArgType.apply(null, x));;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////}}}
|
||||
////////////////////// PUBLIC SECTION //////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////{{{
|
||||
@@ -528,57 +548,15 @@ liberator.Commands = function () //{{{
|
||||
|
||||
if (!invalid)
|
||||
{
|
||||
switch (opt[1]) // type
|
||||
let type = argTypes[opt[1]];
|
||||
if (type)
|
||||
{
|
||||
case this.OPTION_NOARG:
|
||||
if (arg != null)
|
||||
arg = type.parse(arg);
|
||||
if (arg == null || arg == NaN)
|
||||
{
|
||||
liberator.echoerr("No argument allowed for option: " + optname);
|
||||
liberator.echoerr("Invalid argument for " + type.description + "option: " + optname);
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case this.OPTION_BOOL:
|
||||
if (arg == "true" || arg == "1" || arg == "on")
|
||||
arg = true;
|
||||
else if (arg == "false" || arg == "0" || arg == "off")
|
||||
arg = false;
|
||||
else
|
||||
{
|
||||
liberator.echoerr("Invalid argument for boolean option: " + optname);
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case this.OPTION_STRING:
|
||||
if (arg == null)
|
||||
{
|
||||
liberator.echoerr("Argument required for string option: " + optname);
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case this.OPTION_INT:
|
||||
arg = parseInt(arg, 10);
|
||||
if (isNaN(arg))
|
||||
{
|
||||
liberator.echoerr("Numeric argument required for integer option: " + optname);
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case this.OPTION_FLOAT:
|
||||
arg = parseFloat(arg);
|
||||
if (isNaN(arg))
|
||||
{
|
||||
liberator.echoerr("Numeric argument required for float option: " + optname);
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
case this.OPTION_LIST:
|
||||
if (arg == null)
|
||||
{
|
||||
liberator.echoerr("Argument required for list option: " + optname);
|
||||
return null;
|
||||
}
|
||||
arg = arg.split(/\s*,\s*/);
|
||||
break;
|
||||
}
|
||||
|
||||
// we have a validator function
|
||||
|
||||
@@ -476,6 +476,11 @@ liberator.Completion = function () //{{{
|
||||
};
|
||||
let javascript = new Javascript();
|
||||
|
||||
function filterFavicon(array, want)
|
||||
{
|
||||
return want ? array : [a[2] ? a.slice(0, 2) : a for ([i, a] in Iterator(array))];
|
||||
}
|
||||
|
||||
function buildSubstrings(str, filter)
|
||||
{
|
||||
if (filter == "")
|
||||
@@ -618,7 +623,7 @@ liberator.Completion = function () //{{{
|
||||
cacheResults[key] = generate(filter);
|
||||
cacheFilter[key] = filter;
|
||||
if (cacheResults[key].length)
|
||||
return cacheResults[key] = this[method].apply(this, [cacheResults[key], filter].concat(Array.splice(arguments, 4)));
|
||||
return cacheResults[key] = this[method].apply(this, [cacheResults[key], filter].concat(Array.slice(arguments, 4)));
|
||||
return [];
|
||||
},
|
||||
|
||||
@@ -659,7 +664,7 @@ liberator.Completion = function () //{{{
|
||||
{
|
||||
var url = elem[0] || "";
|
||||
var title = elem[1] || "";
|
||||
var tags = elem[3] || [];
|
||||
var tags = elem.tags || elem[3] || [];
|
||||
if (ignorecase)
|
||||
{
|
||||
url = url.toLowerCase();
|
||||
@@ -923,7 +928,7 @@ liberator.Completion = function () //{{{
|
||||
search: function search(filter)
|
||||
{
|
||||
let [, keyword, args] = filter.match(/^\s*(\S*)\s*(.*)/);
|
||||
let keywords = liberator.bookmarks.getKeywords().map(function (k) [k[0], k[1], k[3], k[2]]);
|
||||
let keywords = liberator.bookmarks.getKeywords();
|
||||
let engines = this.filter(keywords.concat(liberator.bookmarks.getSearchEngines()), filter, false, true);
|
||||
|
||||
let generate = function () {
|
||||
@@ -1064,7 +1069,7 @@ liberator.Completion = function () //{{{
|
||||
else if (c == "S")
|
||||
completions.push(this.searchEngineSuggest(filter, suggestEngineAlias)[1]);
|
||||
else if (c == "b")
|
||||
completions.push(liberator.bookmarks.get(filter).map(function (a) [a[0], a[1], a[5]]));
|
||||
completions.push(liberator.bookmarks.get(filter));
|
||||
else if (c == "h")
|
||||
completions.push(liberator.history.get(filter));
|
||||
else if (c == "l" && completionService) // add completions like Firefox's smart location bar
|
||||
|
||||
@@ -422,4 +422,43 @@ liberator.util = { //{{{
|
||||
},
|
||||
}; //}}}
|
||||
|
||||
liberator.util.Struct = function Struct()
|
||||
{
|
||||
let self = this instanceof Struct ? this : new Struct();
|
||||
if (!arguments.length)
|
||||
return self;
|
||||
|
||||
let args = Array.slice(arguments);
|
||||
self.__defineGetter__("length", function () args.length);
|
||||
self.__defineGetter__("members", function () args.slice());
|
||||
for (let arg in Iterator(args))
|
||||
{
|
||||
let [i, name] = arg;
|
||||
self.__defineGetter__(name, function () this[i]);
|
||||
self.__defineSetter__(name, function (val) { this[i] = val; });
|
||||
}
|
||||
function ConStructor()
|
||||
{
|
||||
let self = this instanceof arguments.callee ? this : new arguments.callee();
|
||||
for (let [k, v] in Iterator(Array.slice(arguments)))
|
||||
self[k] = v;
|
||||
return self;
|
||||
}
|
||||
ConStructor.prototype = self;
|
||||
return self.constructor = ConStructor;
|
||||
}
|
||||
liberator.util.Struct.prototype = {
|
||||
clone: function ()
|
||||
{
|
||||
return this.constructor.apply(null, this.slice());
|
||||
},
|
||||
// Iterator over our named members
|
||||
__iterator__: function () ([v, this[v]] for ([k, v] in this.members))
|
||||
}
|
||||
// Add no-sideeffect array methods. Can't set new Array() as the prototype or
|
||||
// get length() won't work.
|
||||
for (let [,k] in Iterator(["concat", "every", "filter", "forEach", "indexOf", "join", "lastIndexOf",
|
||||
"map", "reduce", "reduceRight", "reverse", "slice", "some", "sort"]))
|
||||
liberator.util.Struct.prototype[k] = Array.prototype[k];
|
||||
|
||||
// vim: set fdm=marker sw=4 ts=4 et:
|
||||
|
||||
Reference in New Issue
Block a user