mirror of
https://github.com/tridactyl/tridactyl.git
synced 2026-09-10 15:26:18 -04:00
refactored tst specifics into separate class
This commit is contained in:
parent
9e6b18cf2f
commit
0f58004816
|
|
@ -35,7 +35,10 @@ import { PreferenceCompletionSource } from "@src/completions/Preferences"
|
|||
import { RssCompletionSource } from "@src/completions/Rss"
|
||||
import { SessionsCompletionSource } from "@src/completions/Sessions"
|
||||
import { SettingsCompletionSource } from "@src/completions/Settings"
|
||||
import { BufferCompletionSource } from "@src/completions/Tab"
|
||||
import {
|
||||
LinearBufferCompletionSource,
|
||||
BufferTreeCompletionSource,
|
||||
} from "@src/completions/Tab"
|
||||
import { TabAllCompletionSource } from "@src/completions/TabAll"
|
||||
import { ThemeCompletionSource } from "@src/completions/Theme"
|
||||
import { TabHistoryCompletionSource } from "@src/completions/TabHistory"
|
||||
|
|
@ -120,7 +123,8 @@ export function enableCompletions() {
|
|||
BindingsCompletionSource,
|
||||
BmarkCompletionSource,
|
||||
TabAllCompletionSource,
|
||||
BufferCompletionSource,
|
||||
LinearBufferCompletionSource,
|
||||
BufferTreeCompletionSource,
|
||||
ExcmdCompletionSource,
|
||||
ThemeCompletionSource,
|
||||
TabHistoryCompletionSource,
|
||||
|
|
|
|||
|
|
@ -6,9 +6,6 @@ import * as Completions from "@src/completions"
|
|||
import * as config from "@src/lib/config"
|
||||
import * as Messaging from "@src/lib/messaging"
|
||||
|
||||
// TODO: fix # value for TST
|
||||
// TODO: extract TST to a separate class
|
||||
|
||||
class BufferCompletionOption
|
||||
extends Completions.CompletionOptionHTML
|
||||
implements Completions.CompletionOptionFuse {
|
||||
|
|
@ -21,7 +18,6 @@ class BufferCompletionOption
|
|||
public isAlternative = false,
|
||||
container: browser.contextualIdentities.ContextualIdentity,
|
||||
public tabIndex: number,
|
||||
searchId: number,
|
||||
titlePrefix: number,
|
||||
) {
|
||||
super()
|
||||
|
|
@ -56,7 +52,7 @@ class BufferCompletionOption
|
|||
this.fuseKeys.push(preplain)
|
||||
|
||||
// Push properties we want to fuzmatch on
|
||||
this.fuseKeys.push(String(searchId), tab.title, tab.url)
|
||||
this.fuseKeys.push(String(titlePrefix), tab.title, tab.url)
|
||||
|
||||
// Create HTMLElement
|
||||
const favIconUrl = tab.favIconUrl
|
||||
|
|
@ -78,7 +74,7 @@ class BufferCompletionOption
|
|||
}
|
||||
}
|
||||
|
||||
export class BufferCompletionSource extends Completions.CompletionSourceFuse {
|
||||
abstract class BufferCompletionSource extends Completions.CompletionSourceFuse {
|
||||
public options: BufferCompletionOption[]
|
||||
private shouldSetStateFromScore = true
|
||||
|
||||
|
|
@ -87,29 +83,13 @@ export class BufferCompletionSource extends Completions.CompletionSourceFuse {
|
|||
// callback faffery
|
||||
// - sort out the element redrawing.
|
||||
|
||||
constructor(private _parent) {
|
||||
super(
|
||||
[
|
||||
"tab",
|
||||
"tabclose",
|
||||
"tabdetach",
|
||||
"tabduplicate",
|
||||
"tabmove",
|
||||
"tabrename",
|
||||
"tabdiscard",
|
||||
"pin",
|
||||
"tstmove",
|
||||
"tstmoveafter",
|
||||
"tstattach",
|
||||
],
|
||||
"BufferCompletionSource",
|
||||
"Tabs",
|
||||
)
|
||||
constructor(_parent, prefixes: string[], className: string) {
|
||||
super(prefixes, className, "Tabs")
|
||||
this.sortScoredOptions = true
|
||||
this.shouldSetStateFromScore =
|
||||
config.get("completions", "Tab", "autoselect") === "true"
|
||||
this.updateOptions()
|
||||
this._parent.appendChild(this.node)
|
||||
_parent.appendChild(this.node)
|
||||
|
||||
Messaging.addListener("tab_changes", () => this.reactToTabChanges())
|
||||
}
|
||||
|
|
@ -133,30 +113,19 @@ export class BufferCompletionSource extends Completions.CompletionSourceFuse {
|
|||
|
||||
/** Score with fuse unless query is a single # or looks like a tab index */
|
||||
scoredOptions(
|
||||
exstr: string,
|
||||
query: string,
|
||||
options = this.options,
|
||||
): Completions.ScoredOption[] {
|
||||
const [prefix, query] = this.splitOnPrefix(exstr)
|
||||
const args = query.trim().split(/\s+/gu)
|
||||
if (args.length === 1) {
|
||||
if (args[0] === "#") {
|
||||
const arg = args[0]
|
||||
if (arg === "#") {
|
||||
return this.optionsLike(option => option.isAlternative, options)
|
||||
}
|
||||
|
||||
const arg = Number(args[0])
|
||||
// In TST case argument is tabId
|
||||
if (Number.isInteger(arg) && this.isTstCommand(prefix)) {
|
||||
return this.optionsLike(option => option.tabId === arg, options)
|
||||
}
|
||||
|
||||
// if query is an integer n and |n| < options.length
|
||||
if (Number.isInteger(arg)) {
|
||||
let index = arg - 1
|
||||
if (Math.abs(index) < options.length) {
|
||||
index = index.mod(options.length)
|
||||
// options order might change by scored sorting
|
||||
return this.TabscoredOptionsStartsWithN(index, options)
|
||||
}
|
||||
const searchId = Number(arg)
|
||||
if (Number.isInteger(searchId)) {
|
||||
return this.optionsBySearchId(searchId, options)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -164,20 +133,7 @@ export class BufferCompletionSource extends Completions.CompletionSourceFuse {
|
|||
return super.scoredOptions(query)
|
||||
}
|
||||
|
||||
/** Return the scoredOption[] result for the tab index startswith n */
|
||||
private TabscoredOptionsStartsWithN(
|
||||
n: number,
|
||||
options: BufferCompletionOption[],
|
||||
): Completions.ScoredOption[] {
|
||||
const nstr = (n + 1).toString()
|
||||
options.sort((a, b) => a.tabIndex - b.tabIndex)
|
||||
return this.optionsLike(
|
||||
option => (option.tabIndex + 1).toString().startsWith(nstr),
|
||||
options,
|
||||
)
|
||||
}
|
||||
|
||||
private optionsLike(
|
||||
protected optionsLike(
|
||||
predicate: (o: BufferCompletionOption) => boolean,
|
||||
options: BufferCompletionOption[],
|
||||
): Completions.ScoredOption[] {
|
||||
|
|
@ -218,17 +174,14 @@ export class BufferCompletionSource extends Completions.CompletionSourceFuse {
|
|||
tab_container = Containers.DefaultContainer
|
||||
}
|
||||
const isAlternative = tab.index === altTab.index
|
||||
const searchId = this.isTstCommand(prefix) ? tab.id : tab.index + 1
|
||||
const titlePrefix = this.isTstCommand(prefix) ? tab.id : index + 1
|
||||
const completionValue = isAlternative ? "#" : String(titlePrefix)
|
||||
const titlePrefix = this.titlePrefix(index, tab)
|
||||
options.push(
|
||||
new BufferCompletionOption(
|
||||
completionValue,
|
||||
this.completionValue(titlePrefix, isAlternative),
|
||||
tab,
|
||||
isAlternative,
|
||||
tab_container,
|
||||
index,
|
||||
searchId,
|
||||
titlePrefix,
|
||||
),
|
||||
)
|
||||
|
|
@ -264,7 +217,7 @@ export class BufferCompletionSource extends Completions.CompletionSourceFuse {
|
|||
|
||||
/* console.log('updateOptions', this.optionContainer) */
|
||||
if (query && query.trim().length > 0) {
|
||||
this.setStateFromScore(this.scoredOptions(exstr))
|
||||
this.setStateFromScore(this.scoredOptions(query))
|
||||
} else {
|
||||
this.options.forEach(option => (option.state = "normal"))
|
||||
}
|
||||
|
|
@ -314,7 +267,118 @@ export class BufferCompletionSource extends Completions.CompletionSourceFuse {
|
|||
return this.options[option.tabIndex]
|
||||
}
|
||||
|
||||
private isTstCommand(prefix: string): boolean {
|
||||
return prefix.startsWith("tst")
|
||||
/**
|
||||
* Provide identifier, which will be used before tab title in the completion option.
|
||||
* @param index of a tab calculated by Tridactyl
|
||||
* @param tab Tab
|
||||
*/
|
||||
protected abstract titlePrefix(index: number, tab: browser.tabs.Tab): number
|
||||
|
||||
/**
|
||||
* Provide value, which will be used on tab completion (i.e. when user selects tab option using <Space> or <Enter>).
|
||||
* @param index of a tab calculated by Tridactyl
|
||||
* @param tab Tab
|
||||
*/
|
||||
protected abstract completionValue(
|
||||
titlePrefix: number,
|
||||
isAlternative: boolean,
|
||||
): string
|
||||
|
||||
/**
|
||||
* Filter list of options by option identifier.
|
||||
* @param searchId identifier of the option
|
||||
* @param options list of options to search through
|
||||
*/
|
||||
protected abstract optionsBySearchId(
|
||||
searchId: number,
|
||||
options: BufferCompletionOption[],
|
||||
): Completions.ScoredOption[]
|
||||
}
|
||||
|
||||
export class LinearBufferCompletionSource extends BufferCompletionSource {
|
||||
constructor(_parent) {
|
||||
super(
|
||||
_parent,
|
||||
[
|
||||
"tab",
|
||||
"tabclose",
|
||||
"tabdetach",
|
||||
"tabduplicate",
|
||||
"tabmove",
|
||||
"tabrename",
|
||||
"tabdiscard",
|
||||
"pin",
|
||||
],
|
||||
"LinearBufferCompletionSource",
|
||||
)
|
||||
}
|
||||
|
||||
protected titlePrefix(index: number, _tab: browser.tabs.Tab): number {
|
||||
return index + 1
|
||||
}
|
||||
|
||||
protected completionValue(
|
||||
titlePrefix: number,
|
||||
isAlternative: boolean,
|
||||
): string {
|
||||
if (isAlternative) {
|
||||
return "#"
|
||||
}
|
||||
return String(titlePrefix)
|
||||
}
|
||||
|
||||
protected optionsBySearchId(
|
||||
searchId: number,
|
||||
options: BufferCompletionOption[],
|
||||
): Completions.ScoredOption[] {
|
||||
const index = (searchId - 1).mod(options.length)
|
||||
options.sort((a, b) => a.tabIndex - b.tabIndex)
|
||||
return this.tabScoredOptionsStartsWithN(index, options)
|
||||
}
|
||||
|
||||
/** Return the scoredOption[] result for the tab index startswith n */
|
||||
private tabScoredOptionsStartsWithN(
|
||||
n: number,
|
||||
options: BufferCompletionOption[],
|
||||
): Completions.ScoredOption[] {
|
||||
const nstr = (n + 1).toString()
|
||||
return this.optionsLike(
|
||||
option => (option.tabIndex + 1).toString().startsWith(nstr),
|
||||
options,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TST specifics for tab completion.
|
||||
*
|
||||
* At the moment the only difference to linear tabs is that TST source uses tab
|
||||
* ID in place of tab index for identification.
|
||||
*/
|
||||
export class BufferTreeCompletionSource extends BufferCompletionSource {
|
||||
constructor(_parent) {
|
||||
super(
|
||||
_parent,
|
||||
["tstmove", "tstmoveafter", "tstattach"],
|
||||
"BufferTreeCompletionSource",
|
||||
)
|
||||
}
|
||||
|
||||
protected titlePrefix(_index: number, tab: browser.tabs.Tab): number {
|
||||
return tab.id
|
||||
}
|
||||
|
||||
protected completionValue(
|
||||
titlePrefix: number,
|
||||
_isAlternative: boolean,
|
||||
): string {
|
||||
return String(titlePrefix)
|
||||
}
|
||||
|
||||
protected optionsBySearchId(
|
||||
searchId: number,
|
||||
options: BufferCompletionOption[],
|
||||
): Completions.ScoredOption[] {
|
||||
return this.optionsLike(option => option.tabId === searchId, options)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue