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(() => {
|
browser.runtime.onStartup.addListener(() => {
|
||||||
config.getAsync("autocmds", "TriStart").then(aucmds => {
|
config.getAsync("autocmds", "TriStart").then(aucmds => {
|
||||||
const hosts = Object.keys(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 there's only one rule and it's "all", no need to check the hostname
|
||||||
if (hosts.length === 1 && hosts[0] === ".*") {
|
if (hosts.length === 1 && hosts[0] === ".*") {
|
||||||
autocmd_logger.debug(
|
run(hosts[0])
|
||||||
`TriStart matched ${hosts[0]}: ${aucmds[hosts[0]]}`,
|
|
||||||
)
|
|
||||||
controller.acceptExCmd(aucmds[hosts[0]])
|
|
||||||
} else {
|
} else {
|
||||||
native.run("hostname").then(hostname => {
|
native.run("hostname").then(hostname => {
|
||||||
for (const host of hosts) {
|
for (const host of hosts) {
|
||||||
if (new RegExp(host).exec(hostname.content)) {
|
if (new RegExp(host).exec(hostname.content)) {
|
||||||
autocmd_logger.debug(
|
run(host)
|
||||||
`TriStart matched ${host}: ${aucmds[host]}`,
|
|
||||||
)
|
|
||||||
controller.acceptExCmd(aucmds[host])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -189,7 +187,9 @@ for (const requestEvent of webrequests.requestEvents) {
|
||||||
config.getAsync("autocmds", requestEvent).then(aucmds => {
|
config.getAsync("autocmds", requestEvent).then(aucmds => {
|
||||||
if (!aucmds) return
|
if (!aucmds) return
|
||||||
const patterns = Object.keys(aucmds)
|
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(
|
webrequests.registerWebRequestAutocmd(
|
||||||
requestEvent,
|
requestEvent,
|
||||||
pattern,
|
pattern,
|
||||||
|
|
|
||||||
|
|
@ -15,18 +15,19 @@ export const requestEvents = Object.keys(requestEventExpraInfoSpecMap)
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
||||||
export const LISTENERS: Record<string, Record<string, Function>> = {}
|
export const LISTENERS: Record<string, Record<string, Function>> = {}
|
||||||
|
|
||||||
export const registerWebRequestAutocmd = async (
|
export const registerWebRequestAutocmd = (
|
||||||
requestEvent: string,
|
requestEvent: string,
|
||||||
pattern: string,
|
pattern: string,
|
||||||
func: string,
|
func: string | string[],
|
||||||
) => {
|
) => {
|
||||||
// I'm being lazy - strictly the functions map strings to void | blocking responses
|
// I'm being lazy - strictly the functions map strings to void | blocking responses
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
// 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] = {}
|
if (!LISTENERS[requestEvent]) LISTENERS[requestEvent] = {}
|
||||||
|
|
||||||
await browser.webRequest["on" + requestEvent].addListener(
|
browser.webRequest["on" + requestEvent].addListener(
|
||||||
listener,
|
listener,
|
||||||
{ urls: [pattern] },
|
{ urls: [pattern] },
|
||||||
requestEventExpraInfoSpecMap[requestEvent],
|
requestEventExpraInfoSpecMap[requestEvent],
|
||||||
|
|
@ -37,15 +38,15 @@ export const registerWebRequestAutocmd = async (
|
||||||
|
|
||||||
// Remove any previously registered autocmd for the same pattern
|
// Remove any previously registered autocmd for the same pattern
|
||||||
if (oldListener) {
|
if (oldListener) {
|
||||||
await browser.webRequest["on" + requestEvent].removeListener(
|
browser.webRequest["on" + requestEvent].removeListener(
|
||||||
oldListener
|
oldListener
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const unregisterWebRequestAutocmd = async (requestEvent, pattern) => {
|
export const unregisterWebRequestAutocmd = (requestEvent, pattern) => {
|
||||||
if (LISTENERS[requestEvent] && LISTENERS[requestEvent][pattern]) {
|
if (LISTENERS[requestEvent] && LISTENERS[requestEvent][pattern]) {
|
||||||
await browser.webRequest["on" + requestEvent].removeListener(
|
browser.webRequest["on" + requestEvent].removeListener(
|
||||||
LISTENERS[requestEvent][pattern],
|
LISTENERS[requestEvent][pattern],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,7 @@ export class AutocmdCompletionSource extends Completions.CompletionSourceFuse {
|
||||||
// for `autocmd` itself.
|
// for `autocmd` itself.
|
||||||
let description = ""
|
let description = ""
|
||||||
if (is_autocmddelete) {
|
if (is_autocmddelete) {
|
||||||
description = command
|
description = [command].flat().join(" | ")
|
||||||
}
|
}
|
||||||
const opt = new AutocmdCompletionOption(
|
const opt = new AutocmdCompletionOption(
|
||||||
pattern,
|
pattern,
|
||||||
|
|
|
||||||
|
|
@ -2471,14 +2471,16 @@ export async function loadaucmds(cmdType: "DocStart" | "DocLoad" | "DocEnd" | "T
|
||||||
TRI_FIRED_URL: owntab.url,
|
TRI_FIRED_URL: owntab.url,
|
||||||
}
|
}
|
||||||
for (const aukey of aukeyarr) {
|
for (const aukey of aukeyarr) {
|
||||||
for (const [k, v] of Object.entries(replacements)) {
|
for (let aucmd of [aucmds[aukey]].flat()) {
|
||||||
aucmds[aukey] = aucmds[aukey].replace(k, v)
|
for (const [k, v] of Object.entries(replacements)) {
|
||||||
}
|
aucmd = aucmd.replace(k, v)
|
||||||
try {
|
}
|
||||||
autocmd_logger.debug(`${cmdType} matched ${aukey}: ${aucmds[aukey]}`)
|
try {
|
||||||
await controller.acceptExCmd(aucmds[aukey])
|
autocmd_logger.debug(`${cmdType} matched ${aukey}: ${aucmd}`)
|
||||||
} catch (e) {
|
await controller.acceptExCmd(aucmd)
|
||||||
autocmd_logger.error((e as Error).toString())
|
} 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.
|
* - `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.
|
* 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
|
//#background
|
||||||
|
|
@ -4864,10 +4867,10 @@ export async function autocmd(event: string, url: string, ...excmd: string[]) {
|
||||||
if (!getAutocmdEvents().includes(event)) {
|
if (!getAutocmdEvents().includes(event)) {
|
||||||
throw new Error(event + " is not a supported event.")
|
throw new Error(event + " is not a supported event.")
|
||||||
}
|
}
|
||||||
if (webrequests.requestEvents.includes(event)) {
|
const commands = [...new Set([config.USERCONFIG.autocmds?.[event]?.[url] ?? [], excmd.join(" ")].flat())]
|
||||||
await webrequests.registerWebRequestAutocmd(event, url, excmd.join(" "))
|
if (webrequests.requestEvents.includes(event))
|
||||||
}
|
webrequests.registerWebRequestAutocmd(event, url, commands)
|
||||||
return config.set("autocmds", event, url, excmd.join(" "))
|
return config.set("autocmds", event, url, commands)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -4956,14 +4959,25 @@ export function proxyremove(name: string) {
|
||||||
@param event An event from [[autocmd]]
|
@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 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
|
//#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 (!getAutocmdEvents().includes(event)) throw new Error(`${event} is not a supported event.`)
|
||||||
if (webrequests.requestEvents.includes(event)) {
|
const command = excmd.join(" ")
|
||||||
webrequests.unregisterWebRequestAutocmd(event, url)
|
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") {
|
} else if (i === "autocmds") {
|
||||||
for (const a of Object.keys(pconf[i][e])) {
|
for (const a of Object.keys(pconf[i][e])) {
|
||||||
const value = pconf[i][e][a]
|
for (const command of [pconf[i][e][a]].flat())
|
||||||
parseobj.aucmds.push(
|
parseobj.aucmds.push(command === null ? `autocmddelete ${e} ${a}` : `autocmd ${e} ${a} ${command}`)
|
||||||
value === null
|
|
||||||
? `autocmddelete ${e} ${a}`
|
|
||||||
: `autocmd ${e} ${a} ${value}`,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else if (i === "autocontain") {
|
} else if (i === "autocontain") {
|
||||||
parseobj.aucons.push(`autocontain ${e} ${pconf[i][e]}`)
|
parseobj.aucons.push(`autocontain ${e} ${pconf[i][e]}`)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue