Document hint mode binds

This commit is contained in:
Oliver Blanthorn 2019-05-28 13:08:48 +01:00
parent f050f68740
commit 51c73d028e
No known key found for this signature in database
GPG key ID: 2BB8C36BB504BFF3
2 changed files with 70 additions and 11 deletions

View file

@ -1,3 +1,18 @@
/** # Hint mode functions
*
* This file contains functions to interact with hint mode.
*
* If you want to bind them to keyboard shortcuts, be sure to prefix them with "hint.". For example, if you want to bind control-[ to `reset`, use:
*
* ```
* bind --mode=hint <C-[> hint.reset
* ```
*
* Contrary to the main tridactyl help page, this one doesn't tell you whether a specific function is bound to something. For now, you'll have to make do with `:bind` and `:viewconfig`.
*
*/
/** ignore this line */
/** Hint links. /** Hint links.
TODO: TODO:
@ -22,10 +37,14 @@ import {
import { contentState } from "@src/content/state_content" import { contentState } from "@src/content/state_content"
import * as config from "@src/lib/config" import * as config from "@src/lib/config"
import Logger from "@src/lib/logging" import Logger from "@src/lib/logging"
/** @hidden */
const logger = new Logger("hinting") const logger = new Logger("hinting")
import * as keyseq from "@src/lib/keyseq" import * as keyseq from "@src/lib/keyseq"
/** Calclate the distance between two segments. */ /** Calclate the distance between two segments.
* @hidden
* */
function distance(l1: number, r1: number, l2: number, r2: number): number { function distance(l1: number, r1: number, l2: number, r2: number): number {
if (l1 < r2 && r1 > l2) { if (l1 < r2 && r1 > l2) {
return 0 return 0
@ -34,7 +53,9 @@ function distance(l1: number, r1: number, l2: number, r2: number): number {
} }
} }
/** Simple container for the state of a single frame's hints. */ /** Simple container for the state of a single frame's hints.
* @hidden
* */
class HintState { class HintState {
public focusedHint: Hint public focusedHint: Hint
readonly hintHost = document.createElement("div") readonly hintHost = document.createElement("div")
@ -235,9 +256,12 @@ class HintState {
} }
} }
/** @hidden*/
let modeState: HintState let modeState: HintState
/** For each hintable element, add a hint */ /** For each hintable element, add a hint
* @hidden
* */
export function hintPage( export function hintPage(
hintableElements: Element[], hintableElements: Element[],
onSelect: HintSelectedCallback, onSelect: HintSelectedCallback,
@ -313,6 +337,7 @@ export function hintPage(
document.documentElement.appendChild(modeState.hintHost) document.documentElement.appendChild(modeState.hintHost)
} }
/** @hidden */
function defaultHintBuilder() { function defaultHintBuilder() {
switch (config.get("hintfiltermode")) { switch (config.get("hintfiltermode")) {
case "simple": case "simple":
@ -324,6 +349,7 @@ function defaultHintBuilder() {
} }
} }
/** @hidden */
function defaultHintFilter() { function defaultHintFilter() {
switch (config.get("hintfiltermode")) { switch (config.get("hintfiltermode")) {
case "simple": case "simple":
@ -335,6 +361,7 @@ function defaultHintFilter() {
} }
} }
/** @hidden */
function defaultHintChars() { function defaultHintChars() {
if (config.get("hintnames") === "numeric") { if (config.get("hintnames") === "numeric") {
return "1234567890" return "1234567890"
@ -344,6 +371,7 @@ function defaultHintChars() {
/** An infinite stream of hints /** An infinite stream of hints
@hidden
Earlier hints prefix later hints Earlier hints prefix later hints
*/ */
function* hintnames_simple( function* hintnames_simple(
@ -369,6 +397,7 @@ function* hintnames_simple(
h + (n - h**2 - h) / h ** 2 h + (n - h**2 - h) / h ** 2
and so on, but we hardly ever see that many hints, so whatever. and so on, but we hardly ever see that many hints, so whatever.
@hidden
*/ */
function* hintnames_short( function* hintnames_short(
n: number, n: number,
@ -379,7 +408,9 @@ function* hintnames_short(
yield* islice(source, num2skip, n + num2skip) yield* islice(source, num2skip, n + num2skip)
} }
/** Uniform length hintnames */ /** Uniform length hintnames
* @hidden
* */
function* hintnames_uniform( function* hintnames_uniform(
n: number, n: number,
hintchars = defaultHintChars(), hintchars = defaultHintChars(),
@ -397,13 +428,14 @@ function* hintnames_uniform(
) )
} }
} }
/** @hidden */
function* hintnames_numeric(n: number): IterableIterator<string> { function* hintnames_numeric(n: number): IterableIterator<string> {
for (let i = 1; i <= n; i++) { for (let i = 1; i <= n; i++) {
yield String(i) yield String(i)
} }
} }
/** @hidden */
function* hintnames( function* hintnames(
n: number, n: number,
hintchars = defaultHintChars(), hintchars = defaultHintChars(),
@ -418,9 +450,11 @@ function* hintnames(
} }
} }
/** @hidden */
type HintSelectedCallback = (x: any) => any type HintSelectedCallback = (x: any) => any
/** Place a flag by each hintworthy element */ /** Place a flag by each hintworthy element
@hidden */
class Hint { class Hint {
public readonly flag = document.createElement("span") public readonly flag = document.createElement("span")
public readonly rect: ClientRect = null public readonly rect: ClientRect = null
@ -495,8 +529,10 @@ class Hint {
} }
} }
/** @hidden */
type HintBuilder = (els: Element[], onSelect: HintSelectedCallback) => void type HintBuilder = (els: Element[], onSelect: HintSelectedCallback) => void
/** @hidden */
function buildHintsSimple(els: Element[], onSelect: HintSelectedCallback) { function buildHintsSimple(els: Element[], onSelect: HintSelectedCallback) {
const names = hintnames(els.length) const names = hintnames(els.length)
for (const [el, name] of izip(els, names)) { for (const [el, name] of izip(els, names)) {
@ -506,6 +542,7 @@ function buildHintsSimple(els: Element[], onSelect: HintSelectedCallback) {
} }
} }
/** @hidden */
function buildHintsVimperator(els: Element[], onSelect: HintSelectedCallback) { function buildHintsVimperator(els: Element[], onSelect: HintSelectedCallback) {
const names = hintnames(els.length) const names = hintnames(els.length)
// escape the hintchars string so that strange things don't happen // escape the hintchars string so that strange things don't happen
@ -522,6 +559,7 @@ function buildHintsVimperator(els: Element[], onSelect: HintSelectedCallback) {
} }
} }
/** @hidden */
function elementFilterableText(el: Element): string { function elementFilterableText(el: Element): string {
const nodename = el.nodeName.toLowerCase() const nodename = el.nodeName.toLowerCase()
let text: string let text: string
@ -538,9 +576,11 @@ function elementFilterableText(el: Element): string {
return text.slice(0, 2048).toLowerCase() || "" return text.slice(0, 2048).toLowerCase() || ""
} }
/** @hidden */
type HintFilter = (s: string) => void type HintFilter = (s: string) => void
/** Show only hints prefixed by fstr. Focus first match */ /** Show only hints prefixed by fstr. Focus first match
@hidden */
function filterHintsSimple(fstr) { function filterHintsSimple(fstr) {
const active: Hint[] = [] const active: Hint[] = []
let foundMatch let foundMatch
@ -569,6 +609,8 @@ function filterHintsSimple(fstr) {
Consider: This is a poster child for separating data and display. If they Consider: This is a poster child for separating data and display. If they
weren't so tied here we could do a neat dynamic programming thing and just weren't so tied here we could do a neat dynamic programming thing and just
throw the data at a reactalike. throw the data at a reactalike.
@hidden
*/ */
function filterHintsVimperator(fstr, reflow = false) { function filterHintsVimperator(fstr, reflow = false) {
/** Partition a fstr into a tagged array of substrings */ /** Partition a fstr into a tagged array of substrings */
@ -645,7 +687,8 @@ function filterHintsVimperator(fstr, reflow = false) {
} }
} }
/** Remove all hints, reset STATE. /**
* Remove all hints, reset STATE.
**/ **/
function reset() { function reset() {
if (modeState) { if (modeState) {
@ -682,6 +725,8 @@ function pushKey(key) {
2. they're visible 2. they're visible
1. Within viewport 1. Within viewport
2. Not hidden by another element 2. Not hidden by another element
@hidden
*/ */
export function hintables(selectors = DOM.HINTTAGS_selectors, withjs = false) { export function hintables(selectors = DOM.HINTTAGS_selectors, withjs = false) {
let elems = DOM.getElemsBySelector(selectors, []) let elems = DOM.getElemsBySelector(selectors, [])
@ -693,17 +738,20 @@ export function hintables(selectors = DOM.HINTTAGS_selectors, withjs = false) {
} }
/** Returns elements that point to a saveable resource /** Returns elements that point to a saveable resource
* @hidden
*/ */
export function saveableElements() { export function saveableElements() {
return DOM.getElemsBySelector(DOM.HINTTAGS_saveable, [DOM.isVisible]) return DOM.getElemsBySelector(DOM.HINTTAGS_saveable, [DOM.isVisible])
} }
/** Get array of images in the viewport /** Get array of images in the viewport
* @hidden
*/ */
export function hintableImages() { export function hintableImages() {
return DOM.getElemsBySelector(DOM.HINTTAGS_img_selectors, [DOM.isVisible]) return DOM.getElemsBySelector(DOM.HINTTAGS_img_selectors, [DOM.isVisible])
} }
/** @hidden */
export function hintByText(match) { export function hintByText(match) {
return DOM.getElemsBySelector(DOM.HINTTAGS_filter_by_text_selectors, [ return DOM.getElemsBySelector(DOM.HINTTAGS_filter_by_text_selectors, [
DOM.isVisible, DOM.isVisible,
@ -721,6 +769,7 @@ export function hintByText(match) {
} }
/** Array of items that can be killed with hint kill /** Array of items that can be killed with hint kill
@hidden
*/ */
export function killables() { export function killables() {
return DOM.getElemsBySelector(DOM.HINTTAGS_killable_selectors, [ return DOM.getElemsBySelector(DOM.HINTTAGS_killable_selectors, [
@ -728,7 +777,9 @@ export function killables() {
]) ])
} }
/** HintPage wrapper, accepts CSS selectors to build a list of elements */ /** HintPage wrapper, accepts CSS selectors to build a list of elements
* @hidden
* */
export function pipe( export function pipe(
selectors = DOM.HINTTAGS_selectors, selectors = DOM.HINTTAGS_selectors,
action: HintSelectedCallback = _ => _, action: HintSelectedCallback = _ => _,
@ -740,7 +791,9 @@ export function pipe(
}) })
} }
/** HintPage wrapper, accepts array of elements to hint */ /** HintPage wrapper, accepts array of elements to hint
* @hidden
* */
export function pipe_elements( export function pipe_elements(
elements: any = DOM.elementsWithText, elements: any = DOM.elementsWithText,
action: HintSelectedCallback = _ => _, action: HintSelectedCallback = _ => _,
@ -793,6 +846,7 @@ function focusRightHint() {
modeState.changeFocusedHintRight() modeState.changeFocusedHintRight()
} }
/** @hidden */
export function parser(keys: KeyboardEvent[]) { export function parser(keys: KeyboardEvent[]) {
const keymap = {} const keymap = {}
// Build a map of actions that will match hint names // Build a map of actions that will match hint names
@ -826,6 +880,7 @@ export function parser(keys: KeyboardEvent[]) {
return { keys: [], isMatch: false } return { keys: [], isMatch: false }
} }
/** @hidden*/
export function getHintCommands() { export function getHintCommands() {
return { return {
reset, reset,

View file

@ -9,6 +9,8 @@
Tridactyl also provides a few functions to manipulate text in the command line or text areas that can be found [here](/static/docs/modules/_src_lib_editor_.html). There are also a few commands only available in the command line which can be found [here](/static/docs/modules/_src_commandline_frame_.html). Tridactyl also provides a few functions to manipulate text in the command line or text areas that can be found [here](/static/docs/modules/_src_lib_editor_.html). There are also a few commands only available in the command line which can be found [here](/static/docs/modules/_src_commandline_frame_.html).
Ex-commands available exclusively in hint mode are listed [here](/static/docs/modules/_src_content_hinting_.html)
## How to use this help page ## How to use this help page
Every function (excmd) on this page can be called via Tridactyl's command line which we call "ex". There is a slight change in syntax, however. Wherever you see: Every function (excmd) on this page can be called via Tridactyl's command line which we call "ex". There is a slight change in syntax, however. Wherever you see:
@ -3005,7 +3007,7 @@ function parse_bind_args(...args: string[]): bind_args {
[[fillcmdline]] to put a string in the cmdline and focus the cmdline [[fillcmdline]] to put a string in the cmdline and focus the cmdline
(otherwise the string is executed immediately). (otherwise the string is executed immediately).
You can bind to other modes with `bind --mode={insert|ignore|normal|input} ...`, e.g, `bind --mode=insert emacs qall` (NB: unlike vim, all preceeding characters will not be input). You can bind to other modes with `bind --mode={insert|ignore|normal|input|ex|hint} ...`, e.g, `bind --mode=insert emacs qall` (NB: unlike vim, all preceeding characters will not be input), or `bind --mode=hint <C-[> hint.reset`.
See also: See also:
@ -3567,6 +3569,8 @@ export function unset(...keys: string[]) {
To open a hint in the background, the default bind is `F`. To open a hint in the background, the default bind is `F`.
Ex-commands available exclusively in hint mode are listed [here](/static/docs/modules/_src_content_hinting_.html)
Related settings: Related settings:
- "hintchars": "hjklasdfgyuiopqwertnmzxcvb" - "hintchars": "hjklasdfgyuiopqwertnmzxcvb"
- "hintfiltermode": "simple" | "vimperator" | "vimperator-reflow" - "hintfiltermode": "simple" | "vimperator" | "vimperator-reflow"