Add nmode mode

Useful for sending keys to the page in normal mode
and sending keys to Tridactyl in ignore mode
This commit is contained in:
Oliver Blanthorn 2020-05-08 15:05:51 +01:00
parent 30c07f3925
commit 24b6006f80
No known key found for this signature in database
GPG key ID: 2BB8C36BB504BFF3
5 changed files with 85 additions and 0 deletions

View file

@ -7,6 +7,7 @@ import { KeyEventLike } from "@src/lib/keyseq"
import * as hinting from "@src/content/hinting" import * as hinting from "@src/content/hinting"
import * as gobblemode from "@src/parsers/gobblemode" import * as gobblemode from "@src/parsers/gobblemode"
import * as generic from "@src/parsers/genericmode" import * as generic from "@src/parsers/genericmode"
import * as nmode from "@src/parsers/nmode"
const logger = new Logger("controller") const logger = new Logger("controller")
@ -102,6 +103,7 @@ function* ParserController() {
hint: hinting.parser, hint: hinting.parser,
gobble: gobblemode.parser, gobble: gobblemode.parser,
visual: keys => generic.parser("vmaps", keys), visual: keys => generic.parser("vmaps", keys),
nmode: nmode.parser,
} }
while (true) { while (true) {

View file

@ -9,6 +9,7 @@ export type ModeName =
| "gobble" | "gobble"
| "input" | "input"
| "visual" | "visual"
| "nmode"
export class PrevInput { export class PrevInput {
inputId: string inputId: string

View file

@ -134,6 +134,7 @@ import * as finding from "@src/content/finding"
import * as toys from "./content/toys" import * as toys from "./content/toys"
import * as hinting from "@src/content/hinting" import * as hinting from "@src/content/hinting"
import * as gobbleMode from "@src/parsers/gobblemode" import * as gobbleMode from "@src/parsers/gobblemode"
import * as nMode from "@src/parsers/nmode"
ALL_EXCMDS = { ALL_EXCMDS = {
"": CTSELF, "": CTSELF,
@ -4200,6 +4201,17 @@ export async function gobble(nChars: number, endCmd: string) {
// }}} // }}}
/**
* Initialize n [mode] mode mode.
*
* Accepts n valid key sequences in mode then executes endexArr, which defaults to `mode ignore`, e.g. `:nmode normal 1 mode ignore`
*/
//#content
export async function nmode(mode: string, n: number, ...endexArr: string[]) {
const endex = endexArr.join(" ") || "mode ignore"
return nMode.init(endex, mode, n)
}
// {{{TEXT TO SPEECH // {{{TEXT TO SPEECH
/** /**

View file

@ -127,6 +127,7 @@ export class default_config {
"<S-Escape>": "mode normal", "<S-Escape>": "mode normal",
"<C-^>": "tab #", "<C-^>": "tab #",
"<C-6>": "tab #", "<C-6>": "tab #",
"<C-o>": "nmode normal 1 mode ignore",
} }
/** /**
@ -209,6 +210,7 @@ export class default_config {
"<C-d>": "scrollpage 0.5", "<C-d>": "scrollpage 0.5",
"<C-f>": "scrollpage 1", "<C-f>": "scrollpage 1",
"<C-b>": "scrollpage -1", "<C-b>": "scrollpage -1",
"<C-v>": "nmode ignore 1 mode normal", // Is this a terrible idea? Pentadactyl did it http://bug.5digits.org/help/pentadactyl/browsing.xhtml#send-key
$: "scrollto 100 x", $: "scrollto 100 x",
// "0": "scrollto 0 x", // will get interpreted as a count // "0": "scrollto 0 x", // will get interpreted as a count
"^": "scrollto 0 x", "^": "scrollto 0 x",

68
src/parsers/nmode.ts Normal file
View file

@ -0,0 +1,68 @@
/** Accept n [mode] commands then execute the other command */
import { contentState } from "@src/content/state_content"
import * as config from "@src/lib/config"
import * as keyseq from "@src/lib/keyseq"
/** Simple container for the gobble state. */
class NModeState {
public numCommands = 1
public curCommands = 0
public mode = "normal"
public endCommand = ""
}
let modeState: NModeState
/** Init n [mode] mode. After parsing the defined number of commands, execute
`endCmd`. `Escape` cancels the mode and executes `endCmd`. */
export function init(endCommand: string, mode = "normal", numCommands: number = 1) {
contentState.mode = "nmode"
modeState = new NModeState()
modeState.endCommand = endCommand
modeState.numCommands = numCommands
modeState.mode = mode
}
// Borrowed from content/controller_content.ts
const configs = {
normal: "nmaps",
insert: "imaps",
input: "inputmaps",
ignore: "ignoremaps",
visual: "vmaps",
}
/** Receive keypress. If applicable, execute a command. */
export function parser(keys: KeyboardEvent[]) {
// Borrowed from genericmode.ts
const conf = configs[modeState.mode] || modeState.mode + "maps"
let maps: any = config.get(conf)
if (maps === undefined) throw new Error("No binds defined for this mode. Reload page with <C-r> and add binds, e.g. :bind --mode=[mode] <Esc> mode normal")
// If so configured, translate keys using the key translation map
if (config.get("keytranslatemodes")[conf] === "true") {
const translationmap = config.get("keytranslatemap")
keyseq.translateKeysUsingKeyTranslateMap(keys, translationmap)
}
// Convert to KeyMap
maps = new Map(Object.entries(maps))
maps = keyseq.mapstrMapToKeyMap(maps)
// genericmode.ts borrowing ends
const key = keys[0].key
if (key === "Escape") {
const exstr = modeState.endCommand
modeState = undefined
return { keys: [], exstr }
}
const response = keyseq.parse(keys, maps)
if (response.exstr != "") modeState.curCommands += 1
if (modeState.curCommands >= modeState.numCommands) {
response.exstr = "composite " + response.exstr + "; " + modeState.endCommand // NB: this probably breaks any `js` binds
modeState = undefined
}
return response
}