1
0
mirror of https://github.com/gryf/pentadactyl-pm.git synced 2025-12-23 17:22:26 +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"] const faviconService = Components.classes["@mozilla.org/browser/favicon-service;1"]
.getService(Components.interfaces.nsIFaviconService); .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 storage = liberator.storage;
const properties = { url: 0, title: 1, keyword: 2, tags: 3, id: 4, icon: 5 };
function Cache(name, store, serial) function Cache(name, store, serial)
{ {
const rootFolders = [bookmarksService.toolbarFolder, bookmarksService.bookmarksMenuFolder, bookmarksService.unfiledBookmarksFolder]; 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__("bookmarks", function () { this.load(); return bookmarks; });
this.__defineGetter__("keywords", 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)); this.__iterator__ = function () (val for each (val in self.bookmarks));
@@ -67,7 +69,7 @@ liberator.Bookmarks = function () //{{{
let keyword = bookmarksService.getKeywordForBookmark(node.itemId); let keyword = bookmarksService.getKeywordForBookmark(node.itemId);
let tags = taggingService.getTagsForURI(uri, {}) || []; let tags = taggingService.getTagsForURI(uri, {}) || [];
let icon = faviconService.getFaviconImageForPage(uri).spec; 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) function readBookmark(id)
@@ -82,7 +84,7 @@ liberator.Bookmarks = function () //{{{
function deleteBookmark(id) function deleteBookmark(id)
{ {
var length = bookmarks.length; 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; return bookmarks.length < length;
} }
@@ -160,13 +162,13 @@ liberator.Bookmarks = function () //{{{
if (isAnnotation) if (isAnnotation)
return; return;
// liberator.dump("onItemChanged(" + itemId + ", " + property + ", " + value + ")\n"); // 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 (bookmark)
{ {
if (property == "tags") if (property == "tags")
value = taggingService.getTagsForURI(ioService.newURI(bookmark[properties.url], null, null), {}); value = taggingService.getTagsForURI(ioService.newURI(bookmark.url, null, null), {});
if (property in properties) if (property in bookmark)
bookmark[properties[property]] = value; bookmark[property] = value;
storage.fireEvent(name, "change", itemId); storage.fireEvent(name, "change", itemId);
} }
}, },
@@ -184,12 +186,7 @@ liberator.Bookmarks = function () //{{{
let bookmarkObserver = function (key, event, arg) let bookmarkObserver = function (key, event, arg)
{ {
if (event == "add") if (event == "add")
{ liberator.autocommands.trigger("BookmarkAdd", arg);
let args = {};
for (let [k, v] in Iterator(properties))
args[k] = arg[v];
liberator.autocommands.trigger("BookmarkAdd", args);
}
liberator.statusline.updateUrl(); liberator.statusline.updateUrl();
} }
@@ -512,14 +509,15 @@ liberator.Bookmarks = function () //{{{
} }
if (openItems) 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", ( let list = liberator.template.bookmarks("title", (
{ {
url: item[0], url: item.url,
title: item[1], title: item.title,
extra: [['keyword', item[2], "hl-Keyword"], extra: [['keyword', item.keyword, "hl-Keyword"],
['tags', item[3].join(', '), "hl-Tag"]].filter(function (i) i[1]) ['tags', item.tags.join(', '), "hl-Tag"]
].filter(function (i) i[1])
} for each (item in items))); } for each (item in items)));
liberator.commandline.echo(list, liberator.commandline.HL_NORMAL, liberator.commandline.FORCE_MULTILINE); liberator.commandline.echo(list, liberator.commandline.HL_NORMAL, liberator.commandline.FORCE_MULTILINE);
}, },
@@ -566,7 +564,7 @@ liberator.History = function () //{{{
var node = rootNode.getChild(i); var node = rootNode.getChild(i);
// liberator.dump("History child " + node.itemId + ": " + node.title + " - " + node.type); // liberator.dump("History child " + node.itemId + ": " + node.title + " - " + node.type);
if (node.type == node.RESULT_TYPE_URI) // just make sure it's a bookmark 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! // close a container after using it!

View File

@@ -69,7 +69,7 @@ liberator.Buffer = function () //{{{
const XHTML = "http://www.w3.org/1999/xhtml"; const XHTML = "http://www.w3.org/1999/xhtml";
const namespace = "@namespace html url(" + XHTML + ");\n" + const namespace = "@namespace html url(" + XHTML + ");\n" +
"@namespace xul url(http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul);\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); let cssUri = function (css) "data:text/css," + encodeURI(css);
@@ -91,13 +91,13 @@ liberator.Buffer = function () //{{{
if (name && name in names) if (name && name in names)
this.removeSheet(name, null, null, null, system); 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) 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 try
{ {
this.registerSheet(cssUri(wrapCSS(sheet)), !force); this.registerSheet(cssUri(wrapCSS(sheet)), !force);
@@ -110,7 +110,7 @@ liberator.Buffer = function () //{{{
} }
if (name) if (name)
{ {
sheet[REF].push(name); sheet.ref.push(name);
names[name] = sheet; names[name] = sheet;
} }
return null; return null;
@@ -128,9 +128,9 @@ liberator.Buffer = function () //{{{
if (name) if (name)
matches = matches.filter(function (i) sheets[i] == names[name]); matches = matches.filter(function (i) sheets[i] == names[name]);
if (css) if (css)
matches = matches.filter(function (i) sheets[i][CSS] == css); matches = matches.filter(function (i) sheets[i].css == css);
if (filter) 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; return matches;
}, },
@@ -156,10 +156,10 @@ liberator.Buffer = function () //{{{
let sheet = sheets[i]; let sheet = sheets[i];
if (name) if (name)
{ {
sheet[REF].splice(sheet[REF].indexOf(name)); sheet.ref.splice(sheet.ref.indexOf(name));
delete names[name]; delete names[name];
} }
if (!sheet[REF].length) if (!sheet.ref.length)
{ {
sheets.splice(i); sheets.splice(i);
this.unregisterSheet(cssUri(wrapCSS(sheet))); 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 // Filter out the given site, and re-add if there are any left
if (filter) if (filter)
{ {
let sites = sheet[SITES].filter(function (f) f != filter); let sites = sheet.sites.filter(function (f) f != filter);
if (sites.length) if (sites.length)
this.addSheet(name, sites.join(","), css, system, true); this.addSheet(name, sites.join(","), css, system, true);
} }
@@ -195,8 +195,8 @@ liberator.Buffer = function () //{{{
function wrapCSS(sheet) function wrapCSS(sheet)
{ {
let filter = sheet[SITES]; let filter = sheet.sites;
let css = sheet[CSS]; let css = sheet.css;
if (filter[0] == "*") if (filter[0] == "*")
return namespace + css; return namespace + css;
let selectors = filter.map(function (part) (/[*]$/.test(part) ? "url-prefix" : let selectors = filter.map(function (part) (/[*]$/.test(part) ? "url-prefix" :
@@ -266,7 +266,7 @@ liberator.Buffer = function () //{{{
} }
} }
Styles.prototype = { 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); let styles = liberator.storage.newObject("styles", Styles, false);
@@ -829,7 +829,7 @@ liberator.Buffer = function () //{{{
if (!css) if (!css)
{ {
let list = Array.concat([i for (i in styles.userNames)], 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"], let str = liberator.template.tabular(["", "Filter", "CSS"],
["padding: 0 1em 0 1ex; vertical-align: top", "padding: 0 1em 0 0; vertical-align: top"], ["padding: 0 1em 0 1ex; vertical-align: top", "padding: 0 1em 0 0; vertical-align: top"],
([k, v[1].join(","), v[2]] ([k, v[1].join(","), v[2]]
@@ -871,7 +871,9 @@ liberator.Buffer = function () //{{{
{ {
argCount: 1, argCount: 1,
completer: function (filter) [0, liberator.completion.filter( completer: function (filter) [0, liberator.completion.filter(
[[i, <>{s[1].join(",")}: {s[2].replace("\n", "\\n")}</>] for ([i, s] in styles.userSheets)] [[i, <>{s.sites.join(",")}: {s.css.replace("\n", "\\n")}</>]
for ([i, s] in styles.userSheets)
]
.concat([[s, ""] for each (s in styles.sites)]) .concat([[s, ""] for each (s in styles.sites)])
, filter)], , filter)],
literal: true, literal: true,

View File

@@ -186,6 +186,26 @@ liberator.Commands = function () //{{{
return matches; 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 ////////////////////////////////////////// ////////////////////// PUBLIC SECTION //////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////{{{ /////////////////////////////////////////////////////////////////////////////{{{
@@ -528,57 +548,15 @@ liberator.Commands = function () //{{{
if (!invalid) if (!invalid)
{ {
switch (opt[1]) // type let type = argTypes[opt[1]];
if (type)
{ {
case this.OPTION_NOARG: arg = type.parse(arg);
if (arg != null) if (arg == null || arg == NaN)
{ {
liberator.echoerr("No argument allowed for option: " + optname); liberator.echoerr("Invalid argument for " + type.description + "option: " + optname);
return null; 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 // we have a validator function

View File

@@ -476,6 +476,11 @@ liberator.Completion = function () //{{{
}; };
let javascript = new Javascript(); 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) function buildSubstrings(str, filter)
{ {
if (filter == "") if (filter == "")
@@ -618,7 +623,7 @@ liberator.Completion = function () //{{{
cacheResults[key] = generate(filter); cacheResults[key] = generate(filter);
cacheFilter[key] = filter; cacheFilter[key] = filter;
if (cacheResults[key].length) 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 []; return [];
}, },
@@ -659,7 +664,7 @@ liberator.Completion = function () //{{{
{ {
var url = elem[0] || ""; var url = elem[0] || "";
var title = elem[1] || ""; var title = elem[1] || "";
var tags = elem[3] || []; var tags = elem.tags || elem[3] || [];
if (ignorecase) if (ignorecase)
{ {
url = url.toLowerCase(); url = url.toLowerCase();
@@ -923,7 +928,7 @@ liberator.Completion = function () //{{{
search: function search(filter) search: function search(filter)
{ {
let [, keyword, args] = filter.match(/^\s*(\S*)\s*(.*)/); 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 engines = this.filter(keywords.concat(liberator.bookmarks.getSearchEngines()), filter, false, true);
let generate = function () { let generate = function () {
@@ -1064,7 +1069,7 @@ liberator.Completion = function () //{{{
else if (c == "S") else if (c == "S")
completions.push(this.searchEngineSuggest(filter, suggestEngineAlias)[1]); completions.push(this.searchEngineSuggest(filter, suggestEngineAlias)[1]);
else if (c == "b") 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") else if (c == "h")
completions.push(liberator.history.get(filter)); completions.push(liberator.history.get(filter));
else if (c == "l" && completionService) // add completions like Firefox's smart location bar 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: // vim: set fdm=marker sw=4 ts=4 et: