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.
TODO:
@ -22,10 +37,14 @@ import {
import { contentState } from "@src/content/state_content"
import * as config from "@src/lib/config"
import Logger from "@src/lib/logging"
/** @hidden */
const logger = new Logger("hinting")
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 {
if (l1 < r2 && r1 > l2) {
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 {
public focusedHint: Hint
readonly hintHost = document.createElement("div")
@ -235,9 +256,12 @@ class HintState {
}
}
/** @hidden*/
let modeState: HintState
/** For each hintable element, add a hint */
/** For each hintable element, add a hint
* @hidden
* */
export function hintPage(
hintableElements: Element[],
onSelect: HintSelectedCallback,
@ -313,6 +337,7 @@ export function hintPage(
document.documentElement.appendChild(modeState.hintHost)
}
/** @hidden */
function defaultHintBuilder() {
switch (config.get("hintfiltermode")) {
case "simple":
@ -324,6 +349,7 @@ function defaultHintBuilder() {
}
}
/** @hidden */
function defaultHintFilter() {
switch (config.get("hintfiltermode")) {
case "simple":
@ -335,6 +361,7 @@ function defaultHintFilter() {
}
}
/** @hidden */
function defaultHintChars() {
if (config.get("hintnames") === "numeric") {
return "1234567890"
@ -344,6 +371,7 @@ function defaultHintChars() {
/** An infinite stream of hints
@hidden
Earlier hints prefix later hints
*/
function* hintnames_simple(
@ -369,6 +397,7 @@ function* hintnames_simple(
h + (n - h**2 - h) / h ** 2
and so on, but we hardly ever see that many hints, so whatever.
@hidden
*/
function* hintnames_short(
n: number,
@ -379,7 +408,9 @@ function* hintnames_short(
yield* islice(source, num2skip, n + num2skip)
}
/** Uniform length hintnames */
/** Uniform length hintnames
* @hidden
* */
function* hintnames_uniform(
n: number,
hintchars = defaultHintChars(),
@ -397,13 +428,14 @@ function* hintnames_uniform(
)
}
}
/** @hidden */
function* hintnames_numeric(n: number): IterableIterator<string> {
for (let i = 1; i <= n; i++) {
yield String(i)
}
}
/** @hidden */
function* hintnames(
n: number,
hintchars = defaultHintChars(),
@ -418,9 +450,11 @@ function* hintnames(
}
}
/** @hidden */
type HintSelectedCallback = (x: any) => any
/** Place a flag by each hintworthy element */
/** Place a flag by each hintworthy element
@hidden */
class Hint {
public readonly flag = document.createElement("span")
public readonly rect: ClientRect = null
@ -495,8 +529,10 @@ class Hint {
}
}
/** @hidden */
type HintBuilder = (els: Element[], onSelect: HintSelectedCallback) => void
/** @hidden */
function buildHintsSimple(els: Element[], onSelect: HintSelectedCallback) {
const names = hintnames(els.length)
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) {
const names = hintnames(els.length)
// 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 {
const nodename = el.nodeName.toLowerCase()
let text: string
@ -538,9 +576,11 @@ function elementFilterableText(el: Element): string {
return text.slice(0, 2048).toLowerCase() || ""
}
/** @hidden */
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) {
const active: Hint[] = []
let foundMatch
@ -569,6 +609,8 @@ function filterHintsSimple(fstr) {
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
throw the data at a reactalike.
@hidden
*/
function filterHintsVimperator(fstr, reflow = false) {
/** 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() {
if (modeState) {
@ -682,6 +725,8 @@ function pushKey(key) {
2. they're visible
1. Within viewport
2. Not hidden by another element
@hidden
*/
export function hintables(selectors = DOM.HINTTAGS_selectors, withjs = false) {
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
* @hidden
*/
export function saveableElements() {
return DOM.getElemsBySelector(DOM.HINTTAGS_saveable, [DOM.isVisible])
}
/** Get array of images in the viewport
* @hidden
*/
export function hintableImages() {
return DOM.getElemsBySelector(DOM.HINTTAGS_img_selectors, [DOM.isVisible])
}
/** @hidden */
export function hintByText(match) {
return DOM.getElemsBySelector(DOM.HINTTAGS_filter_by_text_selectors, [
DOM.isVisible,
@ -721,6 +769,7 @@ export function hintByText(match) {
}
/** Array of items that can be killed with hint kill
@hidden
*/
export function killables() {
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(
selectors = DOM.HINTTAGS_selectors,
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(
elements: any = DOM.elementsWithText,
action: HintSelectedCallback = _ => _,
@ -793,6 +846,7 @@ function focusRightHint() {
modeState.changeFocusedHintRight()
}
/** @hidden */
export function parser(keys: KeyboardEvent[]) {
const keymap = {}
// Build a map of actions that will match hint names
@ -826,6 +880,7 @@ export function parser(keys: KeyboardEvent[]) {
return { keys: [], isMatch: false }
}
/** @hidden*/
export function getHintCommands() {
return {
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).
Ex-commands available exclusively in hint mode are listed [here](/static/docs/modules/_src_content_hinting_.html)
## 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:
@ -3005,7 +3007,7 @@ function parse_bind_args(...args: string[]): bind_args {
[[fillcmdline]] to put a string in the cmdline and focus the cmdline
(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:
@ -3567,6 +3569,8 @@ export function unset(...keys: string[]) {
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:
- "hintchars": "hjklasdfgyuiopqwertnmzxcvb"
- "hintfiltermode": "simple" | "vimperator" | "vimperator-reflow"