- teramako
- MPL 1.1/GPL 2.0/LGPL 2.1
-
-
- For adding Panorama supports.
- This plugin makes the default feature to not switch to the other group suddenly.
- And add some mappings and commands for Parnorama.
-
-
- Use at your OWN RISK.
- This pluin overwrite many mappings, some commands, and some completions.
-
- New Mappings and Commands
- -
- g@
- countg@
-
-
Switch to AppTab.
- If the current tab is already AppTab, switch to the next AppTab.
-
-
- -
- ]]>
- count<C-S-n>
-
-
Switch to next group.
- Caution: cannot switch to empty group.
-
-
- -
- ]]>
- count<C-S-p>
-
-
Switch to previous group.
-
-
- Main Command
- -
- :panorama :tabview :tabcandy
- :panorama SubCommand
- :tabview SubCommand
- :tabcandy SubCommand
-
-
See the following SubCommands.
-
-
- SubCommands
- -
- mkgroup mkg
- mkgroup! GroupName
-
-
Create new tab group named GroupName. And then, switch to the group.
- If specified !, move the current tab to the group.
-
-
- -
- stashtogroup stash
- stashtogroup! GroupName
-
-
Stash the current tab to GroupName.
- Caution: connnot stash AppTab (pinned tab)
-
-
- -
- switchgroup swg g
- switchgroup GroupName
- swg GroupName
- g GroupName
- countswitchgroup
- countswg
- countg
-
-
Switch group to GroupName
-
-
- -
- rmgroup rmg
- rmggroup! GroupName
-
-
remove group. The current group is used if ommited GroupName
-
-
- -
- pulltab pull
- pulltab buffer
-
-
pull a tab from the other group
-
-
- -
- pintab pin
- pintab
-
-
pin the current tab, if already pinned, unpin.
-
-
- -
- title
- title title GroupName
-
-
update GroupName's title to title.
- if omitted GroupName, update the current group.
-
-
-
->;
-
-/**
- * @method selectVisible {{{
- * 現在表示されているタブでの絶対/相対位置によるタブ選択を行う
- * (tabs.select() だと全タブが対象となる)
- * @param {String} spec
- * @param {Boolean} wrap
- */
-function selectVisible (spec, wrap) {
- if (spec === void(0) || spec === "")
- return;
-
- let tabs = gBrowser.visibleTabs;
- let index;
- if (typeof spec === "number" || /^\d+$/.test(spec)) {
- index = parseInt(spec, 10);
- } else if (spec === "$") {
- index = tabs.length - 1;
- } else if (/^[+-]\d+$/.test(spec)) {
- index = tabs.indexOf(gBrowser.mCurrentTab) + parseInt(spec, 10);
- } else {
- return;
- }
- let length = tabs.length;
- if (index > length - 1)
- index = wrap ? index % length : length - 1;
- else if (index < 0)
- index = wrap ? index % length + length : 0;
-
- gBrowser.mTabContainer.selectedItem = tabs[index];
-} // }}}
-
-/**
- * @method switchTo {{{
- * tabs.switchTo 相当の関数
- * @param {String} buffer
- * @param {Boolean} allowNonUnique
- * @param {Number} count
- * @param {Boolean} reverse
- */
-function switchTo (buffer, allowNonUnique, count, reverse) {
- if (buffer == "")
- return null;
- if (buffer != null) {
- tabs._lastBufferSwitchArgs = buffer;
- tabs._lastBufferSwitchSpecial = allowNonUnique;
- } else {
- buffer = this._lastBufferSwitchArgs;
- if (allowNonUnique === void(0) || allowNonUnique === null)
- allowNonUnique = tabs._lastBufferSwitchSpecial;
- }
-
- if (buffer == "#") {
- tabs.selectAlternateTab();
- return;
- }
-
- let tab = searchTab(buffer);
- if (tab) {
- tabs.select(tab._tPos, false);
- return;
- }
-
- if (!count || count < 1)
- count = 1;
- reverse = !!reverse;
-
- let m = [];
- let lowerBuffer = buffer.toLowerCase();
- let first = tabs.index() + (reverse ? 0 : 1);
- let length = config.tabbrowser.browsers.length;
- for (let [i, ] in tabs.browsers) {
- let index = (i + first) % length;
- let browser = config.tabbrowser.browsers[index];
- let url, title;
- if ("__SS_restoreState" in browser) {
- let entry = browser.__SS_data.entries.slice(-1)[0];
- url = entry.url;
- title = entry.title || url;
- } else {
- url = browser.contentDocument.location.href;
- title = browser.contentDocument.title;
- }
- title = title.toLowerCase();
- if (url == buffer) {
- tabs.select(index, false);
- return;
- }
- if (url.indexOf(buffer) >= 0 || title.indexOf(lowerBuffer) >= 0)
- m.push(index);
- }
- if (m.length == 0)
- liberator.echoerr("E94: No matching buffer for " + buffer);
- else if (m.length > 1 && !allowNonUnique)
- liberator.echoerr("E93: More than one match for " + buffer);
- else {
- if (reverse) {
- index = m.length - count;
- while (index < 0)
- index + m.length;
- } else {
- index = (count - 1) % m.length;
- }
- tabs.select(m[index], false);
- }
-} // }}}
-
-
-/**
- * @method searchTab {{{
- * @param {String} buffer
- * - "{Number}:"
- * - "{GroupName} {Number}:"
- * @return {Element|null}
- */
-function searchTab (buffer) {
- if (buffer == "#") {
- if (tabs.alternate != null && tabs.getTab() != tabs.alternate)
- return tabs.alternate;
- return null;
- }
- let m = buffer.match(/^(\d+):?/);
- if (m)
- return tabs.getTab(parseInt(m[1], 10) -1);
- m = buffer.match(/^(.+?)\s+(\d+):?/);
- if (m) {
- let [, groupName, tabNum] = m;
- tabNum = parseInt(tabNum, 10);
- let group = getGroupByName(groupName)[0];
- if (!group)
- return null;
- let tabItem = group.getChild(tabNum -1);
- if (!tabItem)
- return null;
- return tabItem.tab;
- }
- return null;
-} // }}}
-
-let TV = window.TabView;
-/**
- * @type {Window} TabView._window {{{
- */
-this.__defineGetter__("tabView", function() {
- if (TV && TV._window && TV._window.GroupItems) {
- delete this.tabView;
- this.tabView = TV._window;
- return TV._window;
- } else {
- let wating = true;
- TV._initFrame(function(){ wating = false; })
- while (wating)
- liberator.threadYield(false, true);
- return this.tabView;
- }
-}); // }}}
-
-/**
- * @type {Array} Array of AppTabs
- */
-this.__defineGetter__("appTabs", function() gBrowser.visibleTabs.filter(function(t) t.pinned));
-
-/**
- * @method createGroup {{{
- * @param {String} name GroupName
- * @return {GroupItem}
- */
-function createGroup (name) {
- let pageBounds = tabView.Items.getPageBounds();
- pageBounds.inset(20, 20);
- let box = new tabView.Rect(pageBounds);
- box.width = 50;
- box.height = 50;
- let group = new tabView.GroupItem([], { bounds: box, title: name });
- if (name && group.$title.hasClass("defaultName"))
- group.$title.removeClass("defaultName");
- return group;
-} // }}}
-
-/**
- * @param {String|Number} name GroupName or GroupId
- * @return {GroupItem[]}
- */
-function getGroupByName (name) {
- if (typeof name === "number")
- return tabView.GroupItems.groupItems.filter(function(g) g.id == name);
- return tabView.GroupItems.groupItems.filter(function(g) g.getTitle() == name);
-}
-/**
- * @param {Element} tab
- * @param {GroupItem|Number} group GroupItem object or group id
- */
-function tabMoveToGroup (tab, group) {
- let id = (typeof group == "object") ? group.id : group;
- tabView.GroupItems.moveTabToGroupItem(tab, id);
-}
-
-/**
- * @method switchToGroup {{{
- * @param {String|Number} spec
- * @param {Boolean} wrap
- */
-function switchToGroup (spec, wrap) {
- const GI = tabView.GroupItems
- let current = GI.getActiveGroupItem() || GI.getActiveOrphanTab();
- let groupsAndOrphans = GI.groupItems.concat(GI.getOrphanedTabs());
- let offset = 1, relative = false, index;
- if (typeof spec === "number")
- index = parseInt(spec, 10);
- else if (/^[+-]\d+$/.test(spec)) {
- let buf = parseInt(spec, 10);
- index = groupsAndOrphans.indexOf(current) + buf;
- offset = buf >= 0 ? 1 : -1;
- relative = true;
- } else if (spec != "") {
- if (/^\d+$/.test(spec))
- spec = parseInt(spec, 10);
- let targetGroup = getGroupByName(spec)[0];
- if (targetGroup)
- index = groupsAndOrphans.indexOf(targetGroup);
- else {
- liberator.echoerr("No such group: " + spec);
- return;
- }
- } else {
- return;
- }
- let length = groupsAndOrphans.length;
- let apps = appTabs;
- function groupSwitch (index, wrap) {
- if (index > length - 1)
- index = wrap ? index % length : length - 1;
- else if (index < 0)
- index = wrap ? index % length + length : 0;
-
- let target = groupsAndOrphans[index],
- group = null;
- if (target instanceof tabView.GroupItem) {
- group = target;
- target = target.getActiveTab() || target.getChild(0);
- }
-
- if (target) {
- gBrowser.mTabContainer.selectedItem = target.tab;
- } else if (group && apps.length != 0) {
- GI.setActiveGroupItem(group);
- tabView.UI.goToTab(tabs.getTab(0));
- } else if (relative) {
- groupSwitch(index + offset, true);
- } else {
- liberator.echoerr("Cannot switch to " + spec);
- return;
- }
- }
- groupSwitch(index, wrap);
-} // }}}
-
-/**
- * removeTab {{{
- * @param {Element} tab
- * @param {Number} count
- * @param {Boolean} focusLeftTab
- * @param {Number} quitOnLastTab
- * @see tabs.remove
- */
-function removeTab (tab, count, focusLeftTab, quitOnLastTab) {
- const gb = gBrowser;
- function remove (tab) {
- if (vTabs.length > 1) {
- gb.removeTab(tab);
- } else if (buffer.URL != "about:blank" || gb.webNavigation.sessionHistory.count > 0) {
- gb.loadURI("about:blank");
- } else {
- liberator.beep();
- }
- }
- let vTabs = gb.visibleTabs;
-
- if (typeof count != "number" || count < 1)
- count = 1;
-
- if (quitOnLastTab >= 1 && gb.tabs.length <= count) {
- if (liberator.windows.length > 1)
- window.close();
- else
- liberator.quit(quitOnLastTab == 2);
-
- return;
- }
-
- // delegate selecting a tab to Firefox after the tab removed
- if (count === 1 && !focusLeftTab && tab.owner) {
- remove(tab);
- return;
- }
-
- let index = vTabs.indexOf(tab);
- liberator.assert(index >= 0, "No such tab(s) in the current tabs");
-
- let start, end, selIndex;
- if (focusLeftTab) {
- end = index;
- start = Math.max(0, index - count + 1);
- selIndex = Math.max(0, start - 1);
- } else {
- start = index;
- end = Math.min(index + count, vTabs.length) - 1;
- selIndex = end + 1;
- if (selIndex >= vTabs.length)
- selIndex = start > 0 ? start - 1 : 0;
- }
- gb.mTabContainer.selectedItem = vTabs[selIndex];
- for (let i = end; i >= start; i--) {
- remove(vTabs[i]);
- }
-} // }}}
-
-/**
- * setGroupTitile {{{
- * @param {String} title
- * @param {GroupItem} group
- */
-function setGroupTitle (title, group) {
- let activeGroup = tabView.GroupItems.getActiveGroupItem();
- if (!group)
- group = activeGroup;
- liberator.assert(group, "Missing group");
- group.setTitle(title);
- if (title && group.$title.hasClass("defaultName"))
- group.$title.removeClass("defaultName");
- if (group === activeGroup)
- gBrowser.updateTitlebar();
-} // }}}
-
-// ============================================================================
-// Mappings {{{
-// ============================================================================
-
-/**
- * {count}g@ select {count} of AppTab
- * g@ select AppTab,
- * if already selected, select the next AppTab
- */
-mappings.add([modes.NORMAL], ["g@"],
- "Go to AppTab",
- function (count) {
- let apps = appTabs;
- let i = 0;
- if (count != null)
- i = count - 1;
- else {
- let currentTab = tabs.getTab();
- if (currentTab.pinned)
- i = apps.indexOf(currentTab) + 1;
- i %= apps.length;
- }
- if (apps[i])
- selectVisible(i);
- }, { count: true });
-
-/**
- * Switch to next group
- */
-mappings.add([modes.NORMAL], ["