1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-23 13:12:27 +01:00

Add a Struct() type for things like Bookmarks and Styles

This commit is contained in:
Kris Maglione
2008-10-11 20:44:51 +00:00
parent bad771cddc
commit b84714bba6
5 changed files with 110 additions and 88 deletions

View File

@@ -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!

View File

@@ -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],

View File

@@ -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

View File

@@ -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

View File

@@ -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: