Skip to content

Auto run a tree of commands

gdh1995 edited this page Aug 10, 2021 · 9 revisions

Vimium C has a powerful command named runKey. Not only it can run different keys on different page conditions, but also it supports command "trees" and runs different commands according to whether a previous command succeeds or not.

Tree sytnax

When keys in runKey's options has (, ), ?, :, + or %, it will be parsed as a command tree. The basic syntax is:

  • there're 3 types of node in a tree: key node, list node and branching node
  • a key node means a single mapped command.
    • it can be count prefix + mapped key sequence, or a name of available commands
    • when it means a mapped key, its key name can only include English letters and numbers.
      • for example, 3<c-f1> will work as expected, but <c-=> is invalid and causes an error tip when running
      • when it means <v-...>, then <v- and > can be skipped
    • if it include $c or %c, then its count will be multipled by the count prefix of runKey
  • a list node may include any number of child nodes
    • + is used to join its children, and it can be skipped if there's no ambiguity
    • for example, 3f1c means to run <v-f1c> by 3 times; while 3f%cf means 3f and %cf
  • a branching node means if ... then ... else ...
    • it syntax is <condition> ["?" <then-branch>] [":" <else-branch>]
    • either ? or : can be skipped, so both (a?) and (b:2c) will work
  • to specify priorities, use ( and ) to join some nodes into a list (node)

The running logic is:

  • a key node runs a single command and returns "success" or "failure"
  • a list node runs its children one by one
    • when a child node fails:
      • if the child is a key node, the list itself fails immediately, ignoring following nodes
      • otherwise, if the child is not the last one, then the list continues to run a next child
    • it returns the result of its last child node, or "success" if it's empty
  • a branching node runs its condition node firstly
    • and then choose one between then and else branches according to whether the condition succeeds or not
    • it returns the result of its selected branch

To assign shared options, there're 2 ways:

  1. add options={key1:val1,key2:val2} to a runKey mapping
  2. add "o." prefix to option items, such as o.key1=val1 o.key2=val2

Example

To focus an input in a current frame, and when it fails, go to the top frame / scroll to top and then find an input again, we may write:

map W scrollToTop
map i runKey keys="focusInput?:(mainFrame:W+150wait)%cfocusInput" \
  o.keep o.select="all-line" o.reachable \
  o.prefer="#js-issues-search,#searchEngines"

In the mapping above, 150wait means to wait for 150 milliseconds, which allows page scripts to update UI state.