mirror of
https://github.com/vale981/tridactyl
synced 2025-03-04 17:11:40 -05:00
Merge pull request #4453 from GHolk/hint-exclude
Option to exclude selectors from hint result
This commit is contained in:
commit
0db566cd87
3 changed files with 87 additions and 3 deletions
|
@ -396,6 +396,71 @@ interface Hintables {
|
|||
hintclasses?: string[]
|
||||
}
|
||||
|
||||
/**
|
||||
A convenient javascript interface to hint on specified html elements.
|
||||
The return value is a promise resolving to the selected element,
|
||||
or an AsyncIterator resolving to the selected elements in rapid mode.
|
||||
|
||||
Example usage:
|
||||
|
||||
`tri.hinting_content.hintElements(...).then(element => {tri.dom.simulateClick(element))`
|
||||
|
||||
`for (await e of tri.hinting_content.hintElements(..., {rapid: true}){tri.dom.simulateClick(e)})`
|
||||
|
||||
@param elements a iterator yield html elements
|
||||
@param option a option object. The `option.rapid` specify whether hint in rapid mode. Default value is false. The `option.callback` is executed when a hint is selected if specified. The default callback is a no-op.
|
||||
|
||||
@returns promise resolve to the selected element, or a async iterator in rapid mode.
|
||||
*/
|
||||
export function hintElements(elements: Element[], option = {}) {
|
||||
const hintable = toHintablesArray(Array.from(elements))
|
||||
const rapid = option["rapid"] ?? false
|
||||
const callback = typeof option["callback"] === "function" ?
|
||||
option["callback"] : x => x
|
||||
if (!rapid) {
|
||||
return new Promise((resolve, reject) => {
|
||||
hintPage(hintable, x => x, resolve, reject, rapid)
|
||||
}).then(x => {
|
||||
callback(x)
|
||||
return x
|
||||
})
|
||||
} else {
|
||||
const endDefer = deferCreate()
|
||||
const endPromise = endDefer.promise.catch(error => error)
|
||||
let onSelect = deferCreate()
|
||||
const key = Symbol("select-result")
|
||||
const hintCallback = element => {
|
||||
callback(element)
|
||||
onSelect.resolve({[key]: element})
|
||||
onSelect = deferCreate()
|
||||
}
|
||||
const wrap = async function* () {
|
||||
while (true) {
|
||||
const first = await Promise.race([onSelect.promise, endPromise])
|
||||
if (first && typeof first === "object" && key in first) {
|
||||
yield first[key]
|
||||
} else return await endPromise
|
||||
}
|
||||
}
|
||||
const result = wrap()
|
||||
hintPage(hintable, hintCallback,
|
||||
endDefer.resolve, endDefer.reject, rapid)
|
||||
return result
|
||||
}
|
||||
function deferCreate() {
|
||||
const defer = {
|
||||
resolve: null,
|
||||
reject: null,
|
||||
promise: null,
|
||||
}
|
||||
defer.promise = new Promise((ok, no) => {
|
||||
defer.resolve = ok
|
||||
defer.reject = no
|
||||
})
|
||||
return defer
|
||||
}
|
||||
}
|
||||
|
||||
/** For each hintable element, add a hint
|
||||
* @hidden
|
||||
* */
|
||||
|
|
|
@ -5064,6 +5064,7 @@ const KILL_STACK: Element[] = []
|
|||
- -c [selector] hint links that match the css selector
|
||||
- `bind ;c hint -c [class*="expand"],[class="togg"]` works particularly well on reddit and HN
|
||||
- this works with most other hint modes, with the caveat that if other hint mode takes arguments your selector must contain no spaces, i.e. `hint -c[yourOtherFlag] [selector] [your other flag's arguments, which may contain spaces]`
|
||||
- -x [selector] exclude the matched elements from hinting
|
||||
- -f [text] hint links and inputs that display the given text
|
||||
- `bind <c-e> hint -f Edit`
|
||||
- Backslashes can escape spaces: `bind <c-s> hint -f Save\ as`
|
||||
|
|
|
@ -47,6 +47,7 @@ export interface HintOptions {
|
|||
excmd: null | string
|
||||
pipeAttribute: null | string
|
||||
selectors: string[]
|
||||
selectorsExclude: string[]
|
||||
warnings: string[]
|
||||
}
|
||||
|
||||
|
@ -64,6 +65,7 @@ export class HintConfig implements HintOptions {
|
|||
public excmd = null
|
||||
public pipeAttribute = null
|
||||
public selectors = []
|
||||
public selectorsExclude = []
|
||||
public warnings = []
|
||||
|
||||
public static parse(args: string[]): HintConfig {
|
||||
|
@ -78,6 +80,7 @@ export class HintConfig implements HintOptions {
|
|||
ExpectPipeSelector,
|
||||
ExpectPipeAttribute,
|
||||
ExpectSelectorCallback,
|
||||
ExpectSelectorExclude,
|
||||
}
|
||||
|
||||
const result = new HintConfig()
|
||||
|
@ -150,6 +153,9 @@ export class HintConfig implements HintOptions {
|
|||
case "c":
|
||||
newState = State.ExpectSelector
|
||||
break
|
||||
case "x":
|
||||
newState = State.ExpectSelectorExclude
|
||||
break
|
||||
case "pipe":
|
||||
newState = State.ExpectPipeSelector
|
||||
break
|
||||
|
@ -304,6 +310,11 @@ export class HintConfig implements HintOptions {
|
|||
result.selectors.push(arg)
|
||||
state = State.Initial
|
||||
break
|
||||
case State.ExpectSelectorExclude:
|
||||
// -x, expect a single exclude selector
|
||||
result.selectorsExclude.push(arg)
|
||||
state = State.Initial
|
||||
break
|
||||
case State.ExpectPipeSelector:
|
||||
// -pipe, first expect a selector
|
||||
result.selectors.push(arg)
|
||||
|
@ -401,13 +412,20 @@ export class HintConfig implements HintOptions {
|
|||
)
|
||||
: this.defaultHintables()
|
||||
|
||||
// Do we have text filters to refine this?
|
||||
if (this.textFilter !== null) {
|
||||
for (const elements of hintables) {
|
||||
const textFilter = this.textFilter
|
||||
const exclude = this.selectorsExclude.join(" ")
|
||||
for (const elements of hintables) {
|
||||
// Do we have text filters to refine this?
|
||||
if (textFilter !== null) {
|
||||
elements.elements = elements.elements.filter(
|
||||
hinting.hintByTextFilter(this.textFilter),
|
||||
)
|
||||
}
|
||||
if (exclude) {
|
||||
elements.elements = elements.elements.filter(
|
||||
element => !element.matches(exclude)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return hintables
|
||||
|
|
Loading…
Add table
Reference in a new issue