From e4cef503fcd1ce261a246b2540e826f5cf80401a Mon Sep 17 00:00:00 2001 From: Denis Revunov Date: Wed, 15 Feb 2023 00:09:41 +0300 Subject: [PATCH] Respect MRU order in tab completions and :tab command --- src/completions/Tab.ts | 41 +++++++++++------------------------------ src/excmds.ts | 34 +++++----------------------------- src/lib/webext.ts | 25 +++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 59 deletions(-) diff --git a/src/completions/Tab.ts b/src/completions/Tab.ts index d28c17c8..bc36a3db 100644 --- a/src/completions/Tab.ts +++ b/src/completions/Tab.ts @@ -1,5 +1,5 @@ import * as Perf from "@src/perf" -import { browserBg } from "@src/lib/webext" +import { browserBg, getSortedTabs, prevActiveTab } from "@src/lib/webext" import { enumerate } from "@src/lib/itertools" import * as Containers from "@src/lib/containers" import * as Completions from "@src/completions" @@ -10,7 +10,6 @@ class BufferCompletionOption extends Completions.CompletionOptionHTML implements Completions.CompletionOptionFuse { public fuseKeys = [] - public tabIndex: number public tabId: number constructor( @@ -18,9 +17,10 @@ class BufferCompletionOption tab: browser.tabs.Tab, public isAlternative = false, container: browser.contextualIdentities.ContextualIdentity, + public tabIndex: number, ) { super() - this.tabIndex = tab.index + this.tabId = tab.id // pre contains max four uppercase characters for tab status. @@ -66,7 +66,9 @@ class BufferCompletionOption ${preplain} - ${tab.index + 1}: ${indicator} ${tab.title} + + ${this.tabIndex + 1}: ${indicator} ${tab.title} + ${tab.url} @@ -179,35 +181,14 @@ export class BufferCompletionSource extends Completions.CompletionSourceFuse { } private async fillOptions() { - let tabs: browser.tabs.Tab[] - // Get alternative tab, defined as last accessed tab in any group in // this window. - const currentWindowTabs = await browserBg.tabs.query({ - currentWindow: true, - }) - currentWindowTabs.sort((a, b) => b.lastAccessed - a.lastAccessed) - const altTab = currentWindowTabs[1] - if (config.get("tabshowhidden") === "true") { - tabs = currentWindowTabs - } else { - tabs = await browserBg.tabs.query({ - currentWindow: true, - hidden: false, - }) - tabs.sort((a, b) => b.lastAccessed - a.lastAccessed) - } + const altTab = await prevActiveTab() + const tabs = await getSortedTabs() const options = [] - const useMruTabOrder = config.get("tabsort") === "mru" - if (!useMruTabOrder) { - tabs.sort((a, b) => a.index - b.index) - } else { - tabs.push(tabs.shift()) // If using MRU, move the current tab to the bottom (issue #4168) - } - const container_all = await browserBg.contextualIdentities.query({}) const container_map = new Map() container_all.forEach(elem => @@ -215,18 +196,18 @@ export class BufferCompletionSource extends Completions.CompletionSourceFuse { ) // firefox-default is not in contextualIdenetities container_map.set("firefox-default", Containers.DefaultContainer) - - for (const tab of tabs) { + for (const [index, tab] of tabs.entries()) { let tab_container = container_map.get(tab.cookieStoreId) if (!tab_container) { tab_container = Containers.DefaultContainer } options.push( new BufferCompletionOption( - (tab.index + 1).toString(), + (index + 1).toString(), tab, tab.index === altTab.index, tab_container, + index, ), ) } diff --git a/src/excmds.ts b/src/excmds.ts index afcefd4d..b926cfbb 100644 --- a/src/excmds.ts +++ b/src/excmds.ts @@ -74,7 +74,7 @@ // Shared import * as Messaging from "@src/lib/messaging" -import { ownWinTriIndex, getTriVersion, browserBg, activeTab, activeTabId, activeTabContainerId, openInNewTab, openInNewWindow, openInTab, queryAndURLwrangler, goToTab } from "@src/lib/webext" +import { ownWinTriIndex, getTriVersion, browserBg, activeTab, activeTabId, activeTabContainerId, openInNewTab, openInNewWindow, openInTab, queryAndURLwrangler, goToTab, getSortedTabs, prevActiveTab } from "@src/lib/webext" import * as Container from "@src/lib/containers" import state from "@src/state" import * as State from "@src/state" @@ -2884,26 +2884,13 @@ async function idFromIndex(index?: number | "%" | "#" | string): Promise async function tabFromIndex(index?: number | "%" | "#" | string): Promise { if (index === "#") { // Support magic previous/current tab syntax everywhere - const tabs = await getSortedWinTabs() - if (tabs.length < 2) { - // In vim, '#' is the id of the previous buffer even if said buffer has been wiped - // However, firefox doesn't store tab ids for closed tabs - // Since vim makes '#' default to the current buffer if only one buffer has ever been opened for the current session, it seems reasonable to return the id of the current tab if only one tab is opened in firefox - return activeTab() - } - return tabs[1] + return prevActiveTab() } else if (index !== undefined && index !== "%") { - // Wrap + const tabs = await getSortedTabs() index = Number(index) - index = (index - 1).mod((await browser.tabs.query({ currentWindow: true })).length) + 1 + index = (index - 1).mod(tabs.length) + 1 - // Return id of tab with that index. - return ( - await browser.tabs.query({ - currentWindow: true, - index: index - 1, - }) - )[0] + return tabs[index - 1] } else { return activeTab() } @@ -2941,17 +2928,6 @@ export async function tabdetach(index?: number) { return browser.windows.create({ tabId: await idFromIndex(index) }) } -/** Get list of tabs sorted by most recent use - - @hidden -*/ -//#background_helper -async function getSortedWinTabs(): Promise { - const tabs = await browser.tabs.query({ currentWindow: true }) - tabs.sort((a, b) => (a.lastAccessed < b.lastAccessed ? 1 : -1)) - return tabs -} - /** Toggle fullscreen state */ diff --git a/src/lib/webext.ts b/src/lib/webext.ts index e2304bf7..400fae74 100644 --- a/src/lib/webext.ts +++ b/src/lib/webext.ts @@ -5,6 +5,20 @@ import * as UrlUtil from "@src/lib/url_util" import { sleep } from "@src/lib/patience" import * as R from "ramda" +export async function getSortedTabs(): Promise { + const comp = + config.get("tabsort") === "mru" + ? (a, b) => a.active || -b.active || b.lastAccessed - a.lastAccessed + : (a, b) => a.index - b.index + const hiddenVal = config.get("tabshowhidden") === "true" ? undefined : false + return browserBg.tabs + .query({ + currentWindow: true, + hidden: hiddenVal, + }) + .then(tabs => tabs.sort(comp)) +} + export function inContentScript() { return getContext() === "content" } @@ -70,6 +84,17 @@ export async function activeTabId() { return (await activeTab()).id } +export async function prevActiveTab() { + const tabs = ( + await browserBg.tabs.query({ + currentWindow: true, + }) + ).sort((a, b) => b.lastAccessed - a.lastAccessed) + + if (tabs.length > 1) return tabs[1] + return tabs[0] +} + /** * Return the active window's id. *