+ function matchTabs(args, substr, all) {
+ let filter = args[0];
+
+ if (!filter && args.count == null)
+ yield tabs.getTab();
+ else if (!filter)
+ yield dactyl.assert(tabs.getTab(args.count - 1));
+ else {
+ let matches = /^(\d+)(?:$|:)/.exec(filter);
+ if (matches)
+ yield dactyl.assert(args.count == null &&
+ tabs.getTab(parseInt(matches[1], 10) - 1, !all));
+ else {
+ let str = filter.toLowerCase();
+ for (let tab in values(tabs[all ? "allTabs" : "visibleTabs"])) {
+ let host, title;
+ let browser = tab.linkedBrowser;
+ let uri = browser.currentURI.spec;
+ if (browser.currentURI.schemeIs("about")) {
+ host = "";
+ title = "(Untitled)";
+ }
+ else {
+ host = browser.currentURI.host;
+ title = browser.contentTitle;
+ }
+
+ [host, title, uri] = [host, title, uri].map(String.toLowerCase);
+
+ if (host.indexOf(str) >= 0 || uri == str ||
+ (substr && (title.indexOf(str) >= 0 || uri.indexOf(str) >= 0)))
+ if (args.count == null || --args.count == 0)
+ yield tab;
+ }
+ }
+ }
+ }
+
+ commands.add(["pin[tab]"],
+ "Pin tab as an application tab",
+ function (args) {
+ for (let tab in matchTabs(args))
+ config.browser[!args.bang || !tab.pinned ? "pinTab" : "unpinTab"](tab);
+ },
+ {
+ argCount: "?",
+ bang: true,
+ count: true,
+ completer: function (context, args) {
+ if (!args.bang)
+ context.filters.push(function ({ item }) !item.tab.pinned);
+ completion.buffer(context);
+ }
+ });
+
+ commands.add(["unpin[tab]"],
+ "Unpin tab as an application tab",
+ function (args) {
+ for (let tab in matchTabs(args))
+ config.browser.unpinTab(tab);
+ },
+ {
+ argCount: "?",
+ count: true,
+ completer: function (context, args) {
+ context.filters.push(function ({ item }) item.tab.pinned);
+ completion.buffer(context);
+ }
+ });
+