mirror of
https://github.com/vale981/tridactyl
synced 2025-03-06 01:51:40 -05:00
Document hint mode binds
This commit is contained in:
parent
f050f68740
commit
51c73d028e
2 changed files with 70 additions and 11 deletions
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Add table
Reference in a new issue