2018-04-13 19:28:03 +01:00
|
|
|
import { MsgSafeKeyboardEvent, MsgSafeNode } from "./msgsafe"
|
|
|
|
import { isTextEditable } from "./dom"
|
|
|
|
import { isSimpleKey } from "./keyseq"
|
2017-10-05 18:01:44 +01:00
|
|
|
import state from "./state"
|
2018-04-13 19:28:03 +01:00
|
|
|
import { repeat } from "./excmds_background"
|
2017-12-30 00:46:26 +00:00
|
|
|
import Logger from "./logging"
|
2017-10-05 18:01:44 +01:00
|
|
|
|
2018-04-13 19:28:03 +01:00
|
|
|
import { parser as exmode_parser } from "./parsers/exmode"
|
|
|
|
import { parser as hintmode_parser } from "./hinting_background"
|
|
|
|
import { parser as findmode_parser } from "./finding_background"
|
2017-11-09 00:41:07 +00:00
|
|
|
import * as normalmode from "./parsers/normalmode"
|
|
|
|
import * as insertmode from "./parsers/insertmode"
|
2017-11-15 00:03:34 +00:00
|
|
|
import * as ignoremode from "./parsers/ignoremode"
|
2018-04-13 19:28:03 +01:00
|
|
|
import * as gobblemode from "./parsers/gobblemode"
|
|
|
|
import * as inputmode from "./parsers/inputmode"
|
2017-11-09 00:41:07 +00:00
|
|
|
|
2018-04-13 19:28:03 +01:00
|
|
|
const logger = new Logger("controller")
|
2017-12-04 17:02:31 +01:00
|
|
|
|
2017-10-02 00:59:51 +01:00
|
|
|
/** Accepts keyevents, resolves them to maps, maps to exstrs, executes exstrs */
|
2018-04-13 19:28:03 +01:00
|
|
|
function* ParserController() {
|
2017-11-09 00:41:07 +00:00
|
|
|
const parsers = {
|
|
|
|
normal: normalmode.parser,
|
|
|
|
insert: insertmode.parser,
|
2017-11-15 00:03:34 +00:00
|
|
|
ignore: ignoremode.parser,
|
2017-11-09 00:41:07 +00:00
|
|
|
hint: hintmode_parser,
|
2018-01-28 21:18:29 +00:00
|
|
|
find: findmode_parser,
|
2017-11-20 23:21:49 +00:00
|
|
|
gobble: gobblemode.parser,
|
2017-12-02 23:54:37 +08:00
|
|
|
input: inputmode.parser,
|
2017-11-09 00:41:07 +00:00
|
|
|
}
|
|
|
|
|
2017-10-02 00:59:51 +01:00
|
|
|
while (true) {
|
2018-04-15 23:12:54 +01:00
|
|
|
let exstr = ""
|
|
|
|
let keyEvents = []
|
2017-10-02 00:59:51 +01:00
|
|
|
try {
|
2018-04-13 19:28:03 +01:00
|
|
|
while (true) {
|
2017-10-06 03:28:14 +01:00
|
|
|
let keyevent: MsgSafeKeyboardEvent = yield
|
2017-10-02 00:59:51 +01:00
|
|
|
|
2018-03-07 02:09:41 +00:00
|
|
|
// This code was sort of the cause of the most serious bug in Tridactyl
|
|
|
|
// to date (March 2018).
|
|
|
|
// https://github.com/cmcaine/tridactyl/issues/311
|
2018-04-13 19:28:03 +01:00
|
|
|
if (
|
|
|
|
state.mode != "ignore" &&
|
|
|
|
state.mode != "hint" &&
|
2018-04-22 15:47:38 +01:00
|
|
|
state.mode != "input" &&
|
2018-04-13 19:28:03 +01:00
|
|
|
state.mode != "find"
|
|
|
|
) {
|
2017-11-15 00:03:34 +00:00
|
|
|
if (isTextEditable(keyevent.target)) {
|
2018-04-13 19:28:03 +01:00
|
|
|
if (state.mode !== "insert") {
|
2018-03-07 02:09:41 +00:00
|
|
|
state.mode = "insert"
|
|
|
|
}
|
2018-04-22 15:47:38 +01:00
|
|
|
} else if (state.mode === "insert") {
|
2017-11-15 00:03:34 +00:00
|
|
|
state.mode = "normal"
|
|
|
|
}
|
2018-04-22 15:47:38 +01:00
|
|
|
} else if (
|
|
|
|
state.mode === "input" &&
|
|
|
|
!isTextEditable(keyevent.target)
|
|
|
|
) {
|
|
|
|
state.mode = "normal"
|
2017-10-05 18:01:44 +01:00
|
|
|
}
|
2017-12-30 00:46:26 +00:00
|
|
|
logger.debug(keyevent, state.mode)
|
2017-10-05 18:01:44 +01:00
|
|
|
|
2018-04-15 23:12:54 +01:00
|
|
|
keyEvents.push(keyevent)
|
2017-11-09 00:41:07 +00:00
|
|
|
let response = undefined
|
|
|
|
switch (state.mode) {
|
2018-04-13 19:28:03 +01:00
|
|
|
case "normal":
|
2018-04-15 23:12:54 +01:00
|
|
|
response = (parsers[state.mode] as any)(keyEvents)
|
|
|
|
// Compatibility with other parsers.
|
|
|
|
response.exstr = response.value
|
2017-11-09 00:41:07 +00:00
|
|
|
break
|
|
|
|
default:
|
2017-11-09 21:01:57 +00:00
|
|
|
response = (parsers[state.mode] as any)([keyevent])
|
2017-11-09 00:41:07 +00:00
|
|
|
break
|
|
|
|
}
|
2018-04-15 23:12:54 +01:00
|
|
|
logger.debug(keyEvents, response)
|
2017-10-02 00:59:51 +01:00
|
|
|
|
2018-04-15 23:12:54 +01:00
|
|
|
if (response.exstr) {
|
|
|
|
exstr = response.exstr
|
2017-10-02 00:59:51 +01:00
|
|
|
break
|
|
|
|
} else {
|
2018-04-15 23:12:54 +01:00
|
|
|
keyEvents = response.keys
|
2017-10-02 00:59:51 +01:00
|
|
|
}
|
|
|
|
}
|
2018-04-15 23:12:54 +01:00
|
|
|
acceptExCmd(exstr)
|
2017-10-02 00:59:51 +01:00
|
|
|
} catch (e) {
|
|
|
|
// Rumsfeldian errors are caught here
|
|
|
|
console.error("Tridactyl ParserController fatally wounded:", e)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let generator = ParserController() // var rather than let stops weirdness in repl.
|
|
|
|
generator.next()
|
|
|
|
|
|
|
|
/** Feed keys to the ParserController */
|
2017-10-06 03:28:14 +01:00
|
|
|
export function acceptKey(keyevent: MsgSafeKeyboardEvent) {
|
2017-10-02 00:59:51 +01:00
|
|
|
generator.next(keyevent)
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Parse and execute ExCmds */
|
2018-04-15 23:12:54 +01:00
|
|
|
export function acceptExCmd(exstr: string) {
|
2017-10-05 13:26:28 +01:00
|
|
|
// TODO: Errors should go to CommandLine.
|
2017-10-02 00:59:51 +01:00
|
|
|
try {
|
2018-04-15 23:12:54 +01:00
|
|
|
let [func, args] = exmode_parser(exstr)
|
2017-12-04 17:02:31 +01:00
|
|
|
// Stop the repeat excmd from recursing.
|
2018-04-15 23:12:54 +01:00
|
|
|
if (func !== repeat) state.last_ex_str = exstr
|
2017-10-05 13:26:28 +01:00
|
|
|
try {
|
|
|
|
func(...args)
|
|
|
|
} catch (e) {
|
|
|
|
// Errors from func are caught here (e.g. no next tab)
|
|
|
|
console.error(e)
|
|
|
|
}
|
2017-10-02 00:59:51 +01:00
|
|
|
} catch (e) {
|
2017-10-05 13:26:28 +01:00
|
|
|
// Errors from parser caught here
|
2017-10-02 00:59:51 +01:00
|
|
|
console.error(e)
|
|
|
|
}
|
|
|
|
}
|
2017-11-09 00:41:07 +00:00
|
|
|
|
2018-04-13 19:28:03 +01:00
|
|
|
import { activeTabId } from "./lib/webext"
|
|
|
|
browser.webNavigation.onBeforeNavigate.addListener(async function(details) {
|
|
|
|
if (details.frameId === 0 && details.tabId === (await activeTabId())) {
|
|
|
|
state.mode = "normal"
|
2017-11-09 00:41:07 +00:00
|
|
|
}
|
|
|
|
})
|
2018-04-13 19:28:03 +01:00
|
|
|
browser.tabs.onActivated.addListener(() => (state.mode = "normal"))
|