mirror of
https://github.com/tridactyl/tridactyl.git
synced 2026-09-10 07:16:33 -04:00
Fix #650: allow multiple autocmds per event/match
This commit is contained in:
parent
0e640b05aa
commit
d3629bc8c8
|
|
@ -132,20 +132,18 @@ const autocmd_logger = new Logging.Logger("autocmds")
|
|||
browser.runtime.onStartup.addListener(() => {
|
||||
config.getAsync("autocmds", "TriStart").then(aucmds => {
|
||||
const hosts = Object.keys(aucmds)
|
||||
const run = async host => {
|
||||
autocmd_logger.debug(`TriStart matched ${host}: ${aucmds[host]}`)
|
||||
for (const command of [aucmds[host]].flat()) await controller.acceptExCmd(command)
|
||||
}
|
||||
// If there's only one rule and it's "all", no need to check the hostname
|
||||
if (hosts.length === 1 && hosts[0] === ".*") {
|
||||
autocmd_logger.debug(
|
||||
`TriStart matched ${hosts[0]}: ${aucmds[hosts[0]]}`,
|
||||
)
|
||||
controller.acceptExCmd(aucmds[hosts[0]])
|
||||
run(hosts[0])
|
||||
} else {
|
||||
native.run("hostname").then(hostname => {
|
||||
for (const host of hosts) {
|
||||
if (new RegExp(host).exec(hostname.content)) {
|
||||
autocmd_logger.debug(
|
||||
`TriStart matched ${host}: ${aucmds[host]}`,
|
||||
)
|
||||
controller.acceptExCmd(aucmds[host])
|
||||
run(host)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -189,7 +187,9 @@ for (const requestEvent of webrequests.requestEvents) {
|
|||
config.getAsync("autocmds", requestEvent).then(aucmds => {
|
||||
if (!aucmds) return
|
||||
const patterns = Object.keys(aucmds)
|
||||
patterns.forEach(pattern =>
|
||||
// Async isolates invalid persisted patterns from the rest.
|
||||
// eslint-disable-next-line @typescript-eslint/require-await
|
||||
patterns.forEach(async pattern =>
|
||||
webrequests.registerWebRequestAutocmd(
|
||||
requestEvent,
|
||||
pattern,
|
||||
|
|
|
|||
|
|
@ -15,18 +15,19 @@ export const requestEvents = Object.keys(requestEventExpraInfoSpecMap)
|
|||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
export const LISTENERS: Record<string, Record<string, Function>> = {}
|
||||
|
||||
export const registerWebRequestAutocmd = async (
|
||||
export const registerWebRequestAutocmd = (
|
||||
requestEvent: string,
|
||||
pattern: string,
|
||||
func: string,
|
||||
func: string | string[],
|
||||
) => {
|
||||
// I'm being lazy - strictly the functions map strings to void | blocking responses
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||
const listener = eval(func) as Function
|
||||
const listeners = [func].flat().map(source => (eval(source) as Function).bind(undefined))
|
||||
const listener = details => listeners.reduce((response, listener) => listener(details) ?? response, undefined)
|
||||
|
||||
if (!LISTENERS[requestEvent]) LISTENERS[requestEvent] = {}
|
||||
|
||||
await browser.webRequest["on" + requestEvent].addListener(
|
||||
browser.webRequest["on" + requestEvent].addListener(
|
||||
listener,
|
||||
{ urls: [pattern] },
|
||||
requestEventExpraInfoSpecMap[requestEvent],
|
||||
|
|
@ -37,15 +38,15 @@ export const registerWebRequestAutocmd = async (
|
|||
|
||||
// Remove any previously registered autocmd for the same pattern
|
||||
if (oldListener) {
|
||||
await browser.webRequest["on" + requestEvent].removeListener(
|
||||
browser.webRequest["on" + requestEvent].removeListener(
|
||||
oldListener
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export const unregisterWebRequestAutocmd = async (requestEvent, pattern) => {
|
||||
export const unregisterWebRequestAutocmd = (requestEvent, pattern) => {
|
||||
if (LISTENERS[requestEvent] && LISTENERS[requestEvent][pattern]) {
|
||||
await browser.webRequest["on" + requestEvent].removeListener(
|
||||
browser.webRequest["on" + requestEvent].removeListener(
|
||||
LISTENERS[requestEvent][pattern],
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ export class AutocmdCompletionSource extends Completions.CompletionSourceFuse {
|
|||
// for `autocmd` itself.
|
||||
let description = ""
|
||||
if (is_autocmddelete) {
|
||||
description = command
|
||||
description = [command].flat().join(" | ")
|
||||
}
|
||||
const opt = new AutocmdCompletionOption(
|
||||
pattern,
|
||||
|
|
|
|||
|
|
@ -2471,14 +2471,16 @@ export async function loadaucmds(cmdType: "DocStart" | "DocLoad" | "DocEnd" | "T
|
|||
TRI_FIRED_URL: owntab.url,
|
||||
}
|
||||
for (const aukey of aukeyarr) {
|
||||
for (const [k, v] of Object.entries(replacements)) {
|
||||
aucmds[aukey] = aucmds[aukey].replace(k, v)
|
||||
}
|
||||
try {
|
||||
autocmd_logger.debug(`${cmdType} matched ${aukey}: ${aucmds[aukey]}`)
|
||||
await controller.acceptExCmd(aucmds[aukey])
|
||||
} catch (e) {
|
||||
autocmd_logger.error((e as Error).toString())
|
||||
for (let aucmd of [aucmds[aukey]].flat()) {
|
||||
for (const [k, v] of Object.entries(replacements)) {
|
||||
aucmd = aucmd.replace(k, v)
|
||||
}
|
||||
try {
|
||||
autocmd_logger.debug(`${cmdType} matched ${aukey}: ${aucmd}`)
|
||||
await controller.acceptExCmd(aucmd)
|
||||
} catch (e) {
|
||||
autocmd_logger.error((e as Error).toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4856,6 +4858,7 @@ export function getAutocmdEvents() {
|
|||
* - `TRI_FIRED_URL`: The URL of the document that the tab is displaying.
|
||||
|
||||
* For debugging, use `:set logging.autocmds debug` and check the Firefox web console. `WebRequest` events have no logging.
|
||||
* Running `:autocmd [event] [match] [commmand]` repeatedly will add multiple listeners for the same event, provided `command` is distinct. To remove listeners, see [[autocmddelete]].
|
||||
*
|
||||
*/
|
||||
//#background
|
||||
|
|
@ -4864,10 +4867,10 @@ export async function autocmd(event: string, url: string, ...excmd: string[]) {
|
|||
if (!getAutocmdEvents().includes(event)) {
|
||||
throw new Error(event + " is not a supported event.")
|
||||
}
|
||||
if (webrequests.requestEvents.includes(event)) {
|
||||
await webrequests.registerWebRequestAutocmd(event, url, excmd.join(" "))
|
||||
}
|
||||
return config.set("autocmds", event, url, excmd.join(" "))
|
||||
const commands = [...new Set([config.USERCONFIG.autocmds?.[event]?.[url] ?? [], excmd.join(" ")].flat())]
|
||||
if (webrequests.requestEvents.includes(event))
|
||||
webrequests.registerWebRequestAutocmd(event, url, commands)
|
||||
return config.set("autocmds", event, url, commands)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -4956,14 +4959,25 @@ export function proxyremove(name: string) {
|
|||
@param event An event from [[autocmd]]
|
||||
|
||||
@param url Exactly the "url" you entered when you made the [[autocmd]] you wish to delete. See `:viewconfig autocmds` if you have forgotten.
|
||||
@param excmd The exact command to delete. Omit it to delete every command for the event and URL.
|
||||
*/
|
||||
//#background
|
||||
export function autocmddelete(event: string, url: string) {
|
||||
export async function autocmddelete(event: string, url: string, ...excmd: string[]) {
|
||||
if (!getAutocmdEvents().includes(event)) throw new Error(`${event} is not a supported event.`)
|
||||
if (webrequests.requestEvents.includes(event)) {
|
||||
webrequests.unregisterWebRequestAutocmd(event, url)
|
||||
const command = excmd.join(" ")
|
||||
let commands
|
||||
if (command) {
|
||||
const stored = config.USERCONFIG.autocmds?.[event]?.[url]
|
||||
commands = [stored === undefined ? config.DEFAULTS.autocmds?.[event]?.[url] ?? [] : stored ?? []].flat()
|
||||
if (!commands.includes(command)) return
|
||||
commands = commands.filter(candidate => candidate !== command)
|
||||
}
|
||||
return config.set("autocmds", event, url, null)
|
||||
if (webrequests.requestEvents.includes(event)) {
|
||||
if (commands?.length)
|
||||
webrequests.registerWebRequestAutocmd(event, url, commands)
|
||||
else webrequests.unregisterWebRequestAutocmd(event, url)
|
||||
}
|
||||
return config.set("autocmds", event, url, commands?.length ? commands : null)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -2659,12 +2659,8 @@ const parseConfigHelper = (pconf, parseobj, prefix = []) => {
|
|||
}
|
||||
} else if (i === "autocmds") {
|
||||
for (const a of Object.keys(pconf[i][e])) {
|
||||
const value = pconf[i][e][a]
|
||||
parseobj.aucmds.push(
|
||||
value === null
|
||||
? `autocmddelete ${e} ${a}`
|
||||
: `autocmd ${e} ${a} ${value}`,
|
||||
)
|
||||
for (const command of [pconf[i][e][a]].flat())
|
||||
parseobj.aucmds.push(command === null ? `autocmddelete ${e} ${a}` : `autocmd ${e} ${a} ${command}`)
|
||||
}
|
||||
} else if (i === "autocontain") {
|
||||
parseobj.aucons.push(`autocontain ${e} ${pconf[i][e]}`)
|
||||
|
|
|
|||
Loading…
Reference in a new issue