From 6ed8983b11eaddbf063ef88def6ae7b71688c0e3 Mon Sep 17 00:00:00 2001
From: Kris Maglione
Date: Mon, 3 Oct 2011 23:48:38 -0400
Subject: [PATCH] Kill :bwipeout, :bunload. Change the semantics of :tabc and
:bd: the former operates on visible tabs, the latter on all tabs. Bang
enables regexp matching against title and URL, otherwise site-filter matching
is used.
---
common/content/tabs.js | 152 +++++++++++++++++++++--------------
common/locale/en-US/tabs.xml | 21 +++--
common/modules/util.jsm | 2 +-
pentadactyl/NEWS | 2 +
pentadactyl/TODO | 4 +-
5 files changed, 109 insertions(+), 72 deletions(-)
diff --git a/common/content/tabs.js b/common/content/tabs.js
index aa3a7bd3..15be8462 100644
--- a/common/content/tabs.js
+++ b/common/content/tabs.js
@@ -333,6 +333,60 @@ var Tabs = Module("tabs", {
completion.listCompleter("buffer", filter);
},
+
+ /**
+ * Return an iterator of tabs matching the given filter. If no
+ * filter or count is provided, returns the currently selected
+ * tab. If *filter* is a number or begins with a number followed
+ * by a colon, the tab of that ordinal is returned. Otherwise,
+ * tabs matching the filter as below are returned.
+ *
+ * @param {string} filter The filter. If *regex*, this is a
+ * regular expression against which the tab's URL or title
+ * must match. Otherwise, it is a site filter.
+ * @optional
+ * @param {number|null} count If non-null, return only the
+ * *count*th matching tab.
+ * @optional
+ * @param {boolean} regexp Whether to interpret *filter* as a
+ * regular expression.
+ * @param {boolean} all If true, match against all tabs. If
+ * false, match only tabs in the current tab group.
+ */
+ match: function match(filter, count, regexp, all) {
+ if (!filter && count == null)
+ yield tabs.getTab();
+ else if (!filter)
+ yield dactyl.assert(tabs.getTab(count - 1));
+ else {
+ let matches = /^(\d+)(?:$|:)/.exec(filter);
+ if (matches)
+ yield dactyl.assert(count == null &&
+ tabs.getTab(parseInt(matches[1], 10) - 1, !all));
+ else {
+ if (regexp)
+ regexp = util.regexp(filter, "i");
+ else
+ var matcher = Styles.matchFilter(filter);
+
+ for (let tab in values(tabs[all ? "allTabs" : "visibleTabs"])) {
+ let browser = tab.linkedBrowser;
+ let uri = browser.currentURI;
+ let title;
+ if (uri.spec == "about:blank")
+ title = "(Untitled)";
+ else
+ title = browser.contentTitle;
+
+ if (matcher && matcher(uri)
+ || regexp && (regexp.test(title) || regexp.test(uri.spec)))
+ if (count == null || --count == 0)
+ yield tab;
+ }
+ }
+ }
+ },
+
/**
* Moves a tab to a new position in the tab list.
*
@@ -548,71 +602,45 @@ var Tabs = Module("tabs", {
tabs.updateTabCount();
},
commands: function () {
- commands.add(["bd[elete]", "bw[ipeout]", "bun[load]", "tabc[lose]"],
- "Delete current buffer",
- function (args) {
- let removed = 0;
- for (let tab in matchTabs(args, args.bang, true)) {
- config.removeTab(tab);
- removed++;
- }
-
- if (args[0])
- if (removed > 0)
- dactyl.echomsg(_("buffer.fewerTab" + (removed == 1 ? "" : "s"), removed), 9);
- else
- dactyl.echoerr(_("buffer.noMatching", arg));
- }, {
- argCount: "?",
- bang: true,
- count: true,
- completer: function (context) completion.buffer(context),
- literal: 0,
- privateData: true
- });
-
- 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;
- }
- }
+ [
+ {
+ name: ["bd[elete]"],
+ description: "Delete matching buffers",
+ visible: false
+ },
+ {
+ name: ["tabc[lose]"],
+ description: "Delete matching tabs",
+ visible: true
}
- }
+ ].forEach(function (params) {
+ commands.add(params.name, params.description,
+ function (args) {
+ let removed = 0;
+ for (let tab in tabs.match(args[0], args.count, args.bang, !params.visible)) {
+ config.removeTab(tab);
+ removed++;
+ }
+
+ if (args[0])
+ if (removed > 0)
+ dactyl.echomsg(_("buffer.fewerTab" + (removed == 1 ? "" : "s"), removed), 9);
+ else
+ dactyl.echoerr(_("buffer.noMatching", args[0]));
+ }, {
+ argCount: "?",
+ bang: true,
+ count: true,
+ completer: function (context) completion.buffer(context),
+ literal: 0,
+ privateData: true
+ });
+ });
commands.add(["pin[tab]"],
"Pin tab as an application tab",
function (args) {
- for (let tab in matchTabs(args))
+ for (let tab in tabs.match(args[0], args.count))
config.browser[!args.bang || !tab.pinned ? "pinTab" : "unpinTab"](tab);
},
{
@@ -629,7 +657,7 @@ var Tabs = Module("tabs", {
commands.add(["unpin[tab]"],
"Unpin tab as an application tab",
function (args) {
- for (let tab in matchTabs(args))
+ for (let tab in tabs.match(args[0], args.count))
config.browser.unpinTab(tab);
},
{
@@ -805,7 +833,7 @@ var Tabs = Module("tabs", {
let arg = args[0];
if (tabs.indexFromSpec(arg) == -1) {
- let tabs = [tab for (tab in matchTabs(args, true))];
+ let tabs = [tab for (tab in tabs.match(args[0], args.count, true))];
dactyl.assert(tabs.length, _("error.invalidArgument", arg));
dactyl.assert(tabs.length == 1, _("buffer.multipleMatching", arg));
arg = tabs[0];
diff --git a/common/locale/en-US/tabs.xml b/common/locale/en-US/tabs.xml
index ff387c57..12ff217e 100644
--- a/common/locale/en-US/tabs.xml
+++ b/common/locale/en-US/tabs.xml
@@ -316,10 +316,6 @@
-
d
:tabc :tabclose
- :bun :bunload :bw :bwipeout :bd :bdelete
- :countbdelete! arg
- :countbunload! arg
- :countbwipeout! arg
:counttabclose! arg
countd
@@ -329,9 +325,20 @@
- When used with arg, remove all tabs which contain arg in the
- currently opened hostname. With !, remove all tabs for which
- the currently opened page's URL or title contains arg.
+ When used with arg, remove all visible tabs which match the
+ site-filter arg. With !, remove all tabs
+ for which the currently opened page's URL or title matches the
+ regular expression arg.
+
+
+
+
+-
+ :bd :bdelete
+ :countbdelete! arg
+
+
+ Like :tabclose but include hidden tabs.
diff --git a/common/modules/util.jsm b/common/modules/util.jsm
index ab14517b..f9db472b 100644
--- a/common/modules/util.jsm
+++ b/common/modules/util.jsm
@@ -1098,7 +1098,7 @@ var Util = Module("Util", XPCOM([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
expr = String.replace(expr, /\\(.)/, function (m, m1) {
if (m1 === "c")
flags = flags.replace(/i/g, "") + "i";
- else if (m === "C")
+ else if (m1 === "C")
flags = flags.replace(/i/g, "");
else
return m;
diff --git a/pentadactyl/NEWS b/pentadactyl/NEWS
index dc7697aa..4037315c 100644
--- a/pentadactyl/NEWS
+++ b/pentadactyl/NEWS
@@ -108,6 +108,8 @@
- :style now supports regexp site-filters on Firefox 6+. [b7]
- :qa closes only the current window, per Vim. [b7]
- Added :background command. [b8]
+ - Removed :bwipeout and :bunload. Changed the semantics of :bdelete
+ and :tabclose slightly. [b8]
- Added -id flag to :bmark command and changed updating semantics. [b8]
- Added :exit command. [b7]
- Added :dlclear command. [b7]
diff --git a/pentadactyl/TODO b/pentadactyl/TODO
index cbe8780e..22ca8c1a 100644
--- a/pentadactyl/TODO
+++ b/pentadactyl/TODO
@@ -16,14 +16,14 @@ FEATURES:
9 / should work as in Vim (i.e., save page positions as well as
locations in the history list).
9 clean up error message codes and document
-9 option groups, including buffer-local and site-specific
+9 option groups
+9 global, window-local, tab-local, buffer-local, script-local groups
9 add [count] support to :b* and :tab* commands where missing
8 wherever possible: get rid of dialogs and ask console-like dialog questions
or write error prompts directly on the webpage or with :echo()
8 registers
8 add support for filename special characters such as %
8 :redir and 'verbosefile'
-8 middleclick in content == p, and if command line is open, paste there the clipboard buffer
8 Add information to dactyl/HACKING file about testing and optimization
7 describe-key command (prompt for a key and display its binding with documentation)
7 use ctrl-n/p in insert mode for word completion