]> git.gir.st - VimFx.git/blob - documentation/api.md
Only apply `vimfx.addKeyOverrides` in Normal mode
[VimFx.git] / documentation / api.md
1 <!--
2 This is part of the VimFx documentation.
3 Copyright Simon Lydell 2015, 2016.
4 See the file README.md for copying conditions.
5 -->
6
7 # API
8
9 This file documents VimFx’s [config file] API.
10
11 Both `config.js` and `frame.js` have access to a variable called `vimfx`. Note
12 that while the variables have the same name, they are different and provide
13 different API methods.
14
15
16 ## `config.js` API
17
18 In `config.js`, the following API is available as the variable `vimfx`.
19
20 ### `vimfx.get(...)`, `vimfx.getDefault(...)` and `vimfx.set(...)`
21
22 Gets or sets the (default) value of a VimFx option.
23
24 You can see all options in [defaults.coffee], or by opening [about:config] and
25 filtering by `extensions.vimfx`. Note that you can also access the [special
26 options], which may not be accessed in [about:config], using `vimfx.get(...)`
27 and `vimfx.set(...)`—in fact, this is the _only_ way of accessing those options.
28
29 #### `vimfx.get(option)`
30
31 Gets the value of the VimFx option `option`.
32
33 ```js
34 // Get the value of the Hint characters option:
35 vimfx.get('hints.chars')
36 // Get all keyboard shortcuts (as a string) for the `f` command:
37 vimfx.get('mode.normal.follow')
38 ```
39
40 #### `vimfx.getDefault(option)`
41
42 Gets the default value of the VimFx option `option`.
43
44 Useful when you wish to extend a default, rather than replacing it. See below.
45
46 #### `vimfx.set(option, value)`
47
48 Sets the value of the VimFx option `option` to `value`.
49
50 ```js
51 // Set the value of the Hint characters option:
52 vimfx.set('hints.chars', 'abcdefghijklmnopqrstuvwxyz')
53 // Add yet a keyboard shortcut for the `f` command:
54 vimfx.set('mode.normal.follow', vimfx.getDefault('mode.normal.follow') + ' ee')
55 ```
56
57 When extending an option (as in the second example above), be sure to use
58 `vimfx.getDefault` rather than `vimfx.get`. Otherwise you get a multiplying
59 effect. In the above example, after starting Firefox a few times the option
60 would be `f e e e e`. Also, if you find that example very verbose: Remember
61 that you’re using a programming language! Write a small helper function that
62 suits your needs.
63
64 Note: If you produce conflicting keyboard shortcuts, the order of your code does
65 not matter. The command that comes first in VimFx’s options page in the Add-ons
66 Manager (and in the Keyboard Shortcuts help dialog) gets the shortcut; the other
67 one(s) do(es) not. See the notes about order in [mode object], [category object]
68 and [command object] for more information about order.
69
70 ```js
71 // Even though we set the shortcut for focusing the search bar last, the command
72 // for focusing the location bar “wins”, because it comes first in VimFx’s
73 // options page in the Add-ons Manager.
74 vimfx.set('mode.normal.focus_location_bar', 'ö')
75 vimfx.set('mode.normal.focus_search_bar', 'ö')
76
77 // Swapping their orders also swaps the “winner”.
78 let {commands} = vimfx.modes.normal
79 ;[commands.focus_location_bar.order, commands.focus_search_bar.order] =
80 [commands.focus_search_bar.order, commands.focus_location_bar.order]
81 ```
82
83 ### `vimfx.addCommand(options, fn)`
84
85 Creates a new command.
86
87 `options`:
88
89 - name: `String`. The name used when accessing the command via
90 `vimfx.modes[options.mode].commands[options.name]`. It is also used for the
91 option name (preference key) used to store the shortcuts for the command:
92 `` `custom.mode.${options.mode}.${options.name}` ``.
93 - description: `String`. Shown in the Keyboard Shortcuts help dialog and VimFx’s
94 options page in the Add-ons Manager.
95 - mode: `String`. Defaults to `'normal'`. The mode to add the command to. The
96 value has to be one of the keys of [`vimfx.modes`].
97 - category: `String`. Defaults to `'misc'` for Normal mode and `''`
98 (uncategorized) otherwise. The category to add the command to. The
99 value has to be one of the keys of [`vimfx.get('categories')`][categories].
100 - order: `Number`. Defaults to putting the command at the end of the category.
101 The first of the default commands has the order `100` and then they increase
102 by `100` per command. This allows to put new commands between two already
103 existing ones.
104
105 `fn` is called when the command is activated. See the [onInput] documentation
106 below for more information.
107
108 <strong id="custom-command-shortcuts">Note</strong> that you have to give the
109 new command a shortcut in VimFx’s options page in the Add-ons Manager or set
110 one using `vimfx.set(...)` to able to use the new command.
111
112 ```js
113 vimfx.addCommand({
114 name: 'hello',
115 description: 'Log Hello World',
116 }, () => {
117 console.log('Hello World!')
118 })
119 // Optional:
120 vimfx.set('custom.mode.normal.hello', 'gö')
121 ```
122
123 ### `vimfx.addOptionOverrides(...)` and `vimfx.addKeyOverrides(...)`
124
125 These methods take any number of arguments. Each argument is a rule. The rules
126 are added in order. The methods may be run multiple times.
127
128 A rule is an `Array` of length 2:
129
130 1. The first item is a function that returns `true` if the rule should be
131 applied and `false` if not. This is called the matching function. The
132 matching function receives a [location object] as its only argument.
133 2. The second item is the value that should be used if the rule is applied. This
134 is called the override.
135
136 The rules are tried in the same order they were added. When a matching rule is
137 found it is applied. No more rules will be applied.
138
139 #### `vimfx.addOptionOverrides(...rules)`
140
141 The rules are matched any time the value of a VimFx option is needed.
142
143 The override is an object whose keys are VimFx option names and whose values
144 override the option in question. The values should be formatted as in an
145 [options object].
146
147 ```js
148 vimfx.addOptionOverrides(
149 [ ({hostname, pathname, hash}) =>
150 `${hostname}${pathname}${hash}` === 'google.com/',
151 {prevent_autofocus: false}
152 ]
153 )
154
155 vimfx.addOptionOverrides(
156 [ ({hostname}) => hostname === 'imgur.com',
157 {
158 pattern_attrs: ['class'],
159 pattern_selector: 'div.next-prev .btn',
160 prev_patterns: [/\bnavPrev\b/],
161 next_patterns: [/\bnavNext\b/],
162 }
163 ]
164 )
165 ```
166
167 #### `vimfx.addKeyOverrides(...rules)`
168
169 The rules are matched any time you press a key that is not part of the tail of a
170 multi-key Normal mode shortcut.
171
172 The override is an array of keys which should not activate VimFx commands but be
173 sent to the page.
174
175 This allows to disable commands on specific sites. To _add_ commands on specific
176 sites, add them globally and then disable them on all _other_ sites.
177
178 ```js
179 vimfx.addKeyOverrides(
180 [ location => location.hostname === 'facebook.com',
181 ['j', 'k']
182 ]
183 )
184 ```
185
186 ### `vimfx.send(vim, message, data = null, callback = null)`
187
188 Send `message` (a string) to the instance of `frame.js` in the tab managed by
189 [`vim`][vim object], and pass it `data`. If provided, `callback` must be a
190 function that takes a single argument, which is the data that `frame.js`
191 responds with. `frame.js` uses its [`vimfx.listen(...)`] method to listen for
192 (and optionally respond to) `message`.
193
194 Here is an example:
195
196 ```js
197 // config.js
198 // You get a `vim` instance by using `vimfx.addCommand(...)` or `vimfx.on(...)`.
199 vimfx.send(vim, 'getSelection', {example: 5}, selection => {
200 console.log('Currently selected text:', selection)
201 })
202 ```
203
204 ```js
205 // frame.js
206 vimfx.listen('getSelection', ({example}, callback) => {
207 console.log('`example` should be 5:', example)
208 let selection = content.getSelection().toString()
209 callback(selection)
210 })
211 ```
212
213 What if you want to do it the other way around: Send a message _from_ `frame.js`
214 and listen for it in `config.js`? That’s not the common use case, so VimFx does
215 not provide convenience functions for it. Yes, `vimfx.send(...)`, and
216 `vimfx.listen(...)` in `frame.js`, are just light wrappers around the standard
217 Firefox [Message Manager] to make it easier to create custom commands that ask
218 `frame.js` for information about the current web page (as in the above example).
219 If you want to send messages any other way, you’ll need to use the Message
220 Manager directly. See [the `shutdown` event] for an example.
221
222 (While it would have made sense to provide `vim.send(message, data, callback)`
223 instead of `vimfx.send(vim, message, data, callback)`, the latter was chosen for
224 symmetry between `config.js` and `frame.js`. Use `vimfx.send()` to send
225 messages, and `vimfx.listen()` to listen for them.)
226
227 ### `vimfx.on(eventName, listener)` and `vimfx.off(eventName, listener)`
228
229 After calling `vimfx.on(eventName, listener)`, `listener(data)` will be called
230 when `eventName` is fired, where `data` is an object. Which properties `data`
231 has is specific to each event.
232
233 You may use `vimfx.off(eventName, listener)` if you’d like to remove your
234 added listener for some reason.
235
236 While [`vimfx.send(...)`] and [`vimfx.listen(...)`] are all about passing
237 messages between `config.js` and `frame.js`, `vimfx.on(...)` is all about doing
238 something whenever VimFx emits internal events.
239
240 #### The `locationChange` event
241
242 Occurs when opening a new tab, navigating to a new URL or refreshing the page,
243 causing a full page load.
244
245 `data`:
246
247 - vim: The current [vim object].
248 - location: A [location object].
249
250 This event can be used to enter a different mode by default on some pages (which
251 can be used to replace the blacklist option).
252
253 ```js
254 vimfx.on('locationChange', ({vim, location}) => {
255 if (location.hostname === 'example.com') {
256 vimfx.modes.normal.commands.enter_mode_ignore.run({vim, blacklist: true})
257 }
258 })
259 ```
260
261 #### The `notification` and `hideNotification` events
262
263 The `notification` event occurs when `vim.notify(message)` is called, and means
264 that `message` should be displayed to the user.
265
266 The `hideNotification` event occurs when the `vim.hideNotification()` is called,
267 and means that the current notification is requested to be hidden.
268
269 `data`:
270
271 - vim: The current [vim object].
272 - message: The message that should be notified. Only for the `notification`
273 event.
274
275 Both of these events are emitted even if the [`notifications_enabled`] option is
276 disabled, allowing you to display notifications in any way you want.
277
278 #### The `modeChange` event
279
280 Occurs whenever the current mode in any tab changes. The initial entering of the
281 default mode in new tabs also counts as a mode change.
282
283 `data`:
284
285 - vim: The current [vim object].
286
287 ```js
288 vimfx.on('modeChange', ({vim}) => {
289 let mode = vimfx.modes[vim.mode].name
290 vim.notify(`Entering mode: ${mode}`)
291 })
292 ```
293
294 #### The `TabSelect` event
295
296 Occurs whenever any tab in any window is selected. This is also fired when
297 Firefox starts for the currently selected tab.
298
299 `data`:
300
301 - event: The `event` object passed to the standard Firefox [TabSelect] event.
302
303 #### The `modeDisplayChange` event
304
305 This is basically a combination of the `modeChange` and the `TabSelect` events.
306 The event is useful for knowing when to update UI showing the current mode.
307
308 `data`:
309
310 - vim: The current [vim object].
311
312 (VimFx itself uses this event to update the toolbar [button], by setting
313 `#main-window[vimfx-mode]` to the current mode. You may use this with custom
314 [styling].)
315
316 #### The `focusTypeChange` event
317
318 Occurs when focusing or blurring any element. See also the [`blur_timeout`]
319 option.
320
321 `data`:
322
323 - vim: The current [vim object].
324
325 `data.vim.focusType` has been updated just before this event fires.
326
327 (VimFx itself uses this event to update the toolbar [button], by setting
328 `#main-window[vimfx-focus-type]` to the current focus type. You may use this
329 with custom [styling].)
330
331 #### The `shutdown` event
332
333 Occurs when:
334
335 - VimFx shuts down: When Firefox shuts down, when VimFx is disabled or when
336 VimFx is updated.
337 - When the config file is reloaded using the `gC` command.
338
339 `data`: No data at all is passed.
340
341 If you care about that things you do in `config.js` and `frame.js` are undone
342 when any of the above happens, read on.
343
344 If all you do is using the methods of the `vimfx` object, you shouldn’t need to
345 care about this event.
346
347 The following methods don’t need any undoing:
348
349 - `vimfx.get(...)`
350 - `vimfx.getDefault(...)`
351 - `vimfx.send(...)`
352 - `vimfx.off(...)`
353
354 The following methods are automatically undone when the `shutdown` event fires.
355 This means that if you, for example, add a custom command in `config.js` but
356 then remove it from `config.js` and hit `gC`, the custom command will be gone in
357 VimFx.
358
359 - `vimfx.set(...)`
360 - `vimfx.addCommand(...)`
361 - `vimfx.addOptionOverrides(...)`
362 - `vimfx.addKeyOverrides(...)`
363 - `vimfx.on(...)`
364
365 The following require manual undoing:
366
367 - `vimfx.mode`. Any changes you do here must be manually undone.
368
369 If you add event listeners in `frame.js`, here’s an example of how to remove
370 them on `shutdown`:
371
372 ```js
373 // config.js
374 vimfx.on('shutdown', () => {
375 Components.classes['@mozilla.org/globalmessagemanager;1']
376 .getService(Components.interfaces.nsIMessageListenerManager)
377 // Send this message to _all_ frame scripts.
378 .broadcastAsyncMessage('VimFx-config:shutdown')
379 })
380 ```
381
382 ```js
383 // frame.js
384 let listeners = []
385 function listen(eventName, listener) {
386 addEventListener(eventName, listener, true)
387 listeners.push([eventName, listener])
388 }
389
390 listen('focus', event => {
391 console.log('focused element', event.target)
392 })
393
394 addMessageListener('VimFx-config:shutdown', () => {
395 listeners.forEach(([eventName, listener]) => {
396 removeMessageListener(eventName, listener, true)
397 })
398 })
399 ```
400
401 ### `vimfx.modes`
402
403 An object whose keys are mode names and whose values are [mode object]s.
404
405 This is a very low-level part of the API. It allows to:
406
407 - Access all commands and run them. This is the most common thing that a config
408 file user needs it for.
409
410 ```js
411 let {commands} = vimfx.modes.normal
412 // Inside a custom command:
413 commands.tab_new.run(args)
414 ```
415
416 - Adding new commands. It is recommended to use the `vimfx.addCommand(...)`
417 helper instead. It’s easier.
418
419 ```js
420 vimfx.modes.normal.commands.new_command = {
421 pref: 'extensions.my_extension.mode.normal.new_command',
422 category: 'misc',
423 order: 10000,
424 description: translate('mode.normal.new_command'),
425 run: args => console.log('New command! args:', args)
426 }
427 ```
428
429 - Adding new modes. This is the most advanced customization you can do to VimFx.
430 Expect having to read VimFx’s source code to figure it all out.
431
432 ```js
433 vimfx.modes.new_mode = {
434 name: translate('mode.new_mode'),
435 order: 10000,
436 commands: {},
437 onEnter(args) {},
438 onLeave(args) {},
439 onInput(args, match) {
440 if (match.type === 'full') {
441 match.command.run(args)
442 }
443 return (match.type !== 'none')
444 },
445 }
446 ```
447
448 Have a look at [modes.coffee] and [commands.coffee] for more information.
449
450 ### `vimfx.get('categories')`
451
452 An object whose keys are category names and whose values are [category object]s.
453
454 ```js
455 let categories = vimfx.get('categories')
456
457 // Add a new category.
458 categories.custom = {
459 name: 'Custom commands',
460 order: 10000,
461 }
462
463 // Swap the order of the Location and Tabs categories.
464 ;[commands.focus_location_bar.order, categories.tabs.order] =
465 [categories.tabs.order, commands.focus_location_bar.order]
466 ```
467
468 ### Custom hint commands
469
470 Apart from the standard hint commands, you can create your own.
471
472 You may run any VimFx command by using the following pattern:
473
474 ```js
475 // config.js
476 vimfx.addCommand({
477 name: 'run_other_command_example',
478 description: 'Run other command example',
479 }, (args) => {
480 // Replace 'follow' with any command name here:
481 vimfx.modes.normal.commands.follow.run(args)
482 })
483 ```
484
485 All hint commands (except `eb`) also support `args.callbackOverride`:
486
487 ```js
488 // config.js
489 vimfx.addCommand({
490 name: 'custom_hint_command_example',
491 description: 'Custom hint command example',
492 }, (args) => {
493 vimfx.modes.normal.commands.follow.run(Object.assign({}, args, {
494 callbackOverride({type, href, id, timesLeft}) {
495 console.log('Marker data:', {type, href, id, timesLeft})
496 return (timesLeft > 1)
497 },
498 }))
499 })
500 ```
501
502 This lets you piggy-back on one of the existing hint commands by getting the
503 same hints on screen as that command, but then doing something different with
504 the matched hint marker.
505
506 `callbackOverride` is called with an object with the following properties:
507
508 - type: `String`. The type of the element of the matched hint marker. See
509 [`vimfx.setHintMatcher(...)`] for all possible values.
510
511 - href: `String` or `null`. If `type` is `'link'`, then this is the `href`
512 attribute of the element of the matched hint marker.
513
514 - id: An id that you can pass to [`vimfx.getMarkerElement(...)`] to get the
515 element of the matched hint marker.
516
517 - timesLeft: `Number`. Calling a hint command with a count means that you want
518 to run it _count_ times in a row. This number tells how many times there are
519 left to run. If you don’t provide a count, the number is `1`.
520
521 `callbackOverride` should return `true` if you want the hint markers to
522 re-appear on screen after you’ve matched one of them (as in the `af` command),
523 and `false` if you wish to exit Hints mode. If your command ignores counts,
524 simply always return `false`. Otherwise you most likely want to return
525 `timesLeft > 1`.
526
527 Here’s an example which adds a silly command for marking links with
528 color—`http://` links with red and all other links with green.
529
530 ```js
531 // config.js
532 let {commands} = vimfx.modes.normal
533
534 vimfx.addCommand({
535 name: 'mark_link',
536 category: 'browsing',
537 description: 'Mark link with red or green',
538 }, (args) => {
539 let {vim} = args
540 commands.follow_in_tab.run(Object.assign({}, args, {
541 callbackOverride({type, href, id, timesLeft}) {
542 if (href) {
543 let color = href.startsWith('http://') ? 'red' : 'green'
544 vimfx.send(vim, 'highlight_marker_element', {id, color})
545 }
546 return false
547 },
548 }))
549 })
550 ```
551
552 ```js
553 // frame.js
554 vimfx.listen('highlight_marker_element', ({id, color}) => {
555 let element = vimfx.getMarkerElement(id)
556 if (element) {
557 element.style.backgroundColor = color
558 }
559 })
560 ```
561
562 ### Mode object
563
564 A mode is an object with the following properties:
565
566 - name: `String`. A human readable name of the mode used in the Keyboard
567 Shortcuts help dialog and VimFx’s options page in the Add-ons Manager. Config
568 file users adding custom modes could simply use a hard-coded string; extension
569 authors are encouraged to look up the name from a locale file.
570 - order: `Number`. The first of the default modes has the order `100` and then
571 they increase by `100` per mode. This allows to put new modes between two
572 already existing ones.
573 - commands: `Object`. The keys are command names and the values are [command
574 object]s.
575 - onEnter(data, ...args): `Function`. Called when the mode is entered.
576 - onLeave(data): `Function`. Called when the mode is left.
577 - onInput(data, match): `Function`. Called when a key is pressed.
578
579 #### onEnter, onLeave and onInput
580
581 These methods are called with an object (called `data` above) with the following
582 properties:
583
584 - vim: The current [vim object].
585 - storage: An object unique to the current [vim object] and to the current mode.
586 Allows to share things between commands of the same mode by getting and
587 setting keys on it.
588
589 ##### onEnter
590
591 This method is called with an object as mentioned above, and after that there
592 may be any number of arguments that the mode is free to do whatever it wants
593 with.
594
595 ##### onInput
596
597 The object passed to this method (see above) also has the following properties:
598
599 - event: `Event`. The keydown event object.
600 - count: `Number`. The count for the command. `undefined` if no count. (This is
601 simply a copy of `match.count`. `match` is defined below.)
602
603 The above object should be passed to commands when running them. The mode is
604 free to do whatever it wants with the return value (if any) of the commands it
605 runs.
606
607 It also receives a [match object] as the second argument.
608
609 `onInput` should return `true` if the current keypress should not be passed on
610 to the browser and web pages, and `false` otherwise.
611
612 ### Category object
613
614 A category is an object with the following properties:
615
616 - name: `String`. A human readable name of the category used in the Keyboard
617 Shortcuts help dialog and VimFx’s options page in the Add-ons Manager. Config
618 file users adding custom categories could simply a use hard-coded string;
619 extension authors are encouraged to look up the name from a locale file.
620 - order: `Number`. The first of the default categories is the “uncategorized”
621 category. It has the order `100` and then they increase by `100` per category.
622 This allows to put new categories between two already existing ones.
623
624 ### Command object
625
626 A command is an object with the following properties:
627
628 - pref: `String`. The option name (preference key) used to store the shortcuts
629 for the command.
630 - run(args): `Function`. Called when the command is activated.
631 - description: `String`. A description of the command, shown in the Keyboard
632 Shortcuts help dialog and VimFx’s options page in the Add-ons Manager. Config
633 file users adding custom commands could simply use a hard-coded string;
634 extension authors are encouraged to look up the name from a locale file.
635 - category: `String`. The category to add the command to. The value has to be
636 one of the keys of [`vimfx.get('categories')`][categories].
637 - order: `Number`. The first of the default commands has the order `100` and
638 then they increase by `100` per command. This allows to put new commands
639 between two already existing ones.
640
641 ### Match object
642
643 A `match` object has the following properties:
644
645 - type: `String`. It has one of the following values:
646
647 - `'full'`: The current keypress, together with previous keypresses, fully
648 matches a command shortcut.
649 - `'partial'`: The current keypress, together with previous keypresses,
650 partially matches a command shortcut.
651 - `'count'`: The current keypress is not part of a command shortcut, but is a
652 digit and contributes to the count of a future matched command.
653 - `'none'`: The current keypress is not part of a command shortcut and does
654 not contribute to a count.
655
656 - likelyConflict: `Boolean`. This is `true` if the current keypress is likely to
657 cause conflicts with default Firefox behavior of that key, and `false`
658 otherwise. A mode might not want to run commands and suppress the event if
659 this value is `true`. VimFx uses the current keypress and `vim.focusType` of
660 the current [vim object] to decide if the current keypress is a likely
661 conflict:
662
663 1. If the key is part of the tail of a shortcut, it is never a conflict.
664 2. If `vim.focusType` is `'activatable'` or `'adjustable'` and the key is
665 present in [`activatable_element_keys`] or [`adjustable_element_keys`]
666 (respectively), then it is a likely conflict.
667 3. Finally, unless `vim.focusType` is `'none'`, then it is a likely conflict.
668 This most commonly means that a text input is focused.
669
670 Note that any VimFx shortcut starting with a keypress involving a modifier is
671 _very_ likely to conflict with either a Firefox default shortcut or a shortcut
672 from some other add-on. This is _not_ attempted to be detected in any way.
673 Instead, VimFx uses no modifiers in any default Normal mode shortcuts, leaving
674 it up to you to choose modifier-shortcuts that work out for you if you want
675 such shortcuts. In other words, for modifier-shortcuts the point of VimFx _is_
676 to conflict (overriding default shortcuts).
677
678 - command: `null` unless `type` is `'full'`. Then it is the matched command (a
679 [command object]).
680
681 The matched command should usually be run at this point. It is suitable to
682 pass on the object passed to [onInput] to the command. Some modes might choose
683 to add extra properties to the object first. (That is favored over passing
684 several arguments, since it makes it easier for the command to in turn pass
685 the same data it got on to another command, if needed.)
686
687 Usually the return value of the command isn’t used, but that’s up to the mode.
688
689 - count: `Number`. The count for the command. `undefined` if no count.
690
691 - specialKeys: `Object`. The keys may be any of the following:
692
693 - `<force>`
694 - `<late>`
695
696 If a key exists, its value is always `true`. The keys that exist indicate the
697 [special keys] for the sequence used for the matched command (if any).
698
699 - keyStr: `String`. The current keypress represented as a string.
700
701 - unmodifiedKey: `String`. `keyStr` without modifiers.
702
703 - rawKey: `String`. Unchanged [`event.key`].
704
705 - rawCode: `String`. Unchanged [`event.code`].
706
707 - toplevel: `Boolean`. Whether or not the match was a toplevel match in the
708 shortcut key tree. This is `true` unless the match is part of the tail of a
709 multi-key shortcut.
710
711 - discard(): `Function`. Discards keys pressed so far: If `type` is `'partial'`
712 or `'count'`. For example, if you have typed `12g`, run `match.discard()` and
713 then press `$`, the `$` command will be run instead of `12g$`.
714
715 ### Vim object
716
717 There is one `vim` object per tab.
718
719 A `vim` object has the following properties:
720
721 - window: [`Window`]. The current Firefox window object. Most commands
722 interacting with Firefox’s UI use this.
723
724 - browser: [`Browser`]. The `browser` that this vim object handles.
725
726 - options: `Object`. Provides access to all of VimFx’s options. It is an
727 [options object].
728
729 - mode: `String`. The current mode name.
730
731 - focusType: `String`. The type of currently focused element. VimFx decides the
732 type based on how it responds to keystorkes. It has one of the following
733 values:
734
735 - `'ignore'`: Some kind of Vim-style editor. VimFx automatically
736 enters Ignore mode when this focus type is encountered.
737 - `'editable'`: Some kind of text input, a `<select>` element or a
738 “contenteditable” element.
739 - `'activatable'`: An “activatable” element (link or button).
740 (See also the [`activatable_element_keys`] option.)
741 - `'adjustable'`: An “adjustable” element (form control or video
742 player). (See also the [`adjustable_element_keys`] option.)
743 - `'findbar'`: The findbar text input is focused.
744 - `'none'`: The currently focused element does not appear to respond to
745 keystrokes in any special way.
746
747 [The `focusTypeChange` event] is fired whenever `focusType` is updated.
748
749 `match.likelyConflict` of [match object]s depend on `focusType`.
750
751 - isUIEvent(event): `Function`. Returns `true` if `event` occurred in the
752 browser UI, and `false` otherwise (if it occurred in web page content).
753
754 - notify(message): `Function`. Display a notification with the text `message`.
755
756 - hideNotification(): `Function`. Hide the current notification (if any).
757
758 - markPageInteraction(value=true): `Function`. When `value` is `true` (as it is
759 by default when the argument is omitted), marks that the user has interacted
760 with the page. After that [autofocus prevention] is not done anymore. Commands
761 interacting with web page content might want to do this. If `value` is
762 `false`, the state is reset and autofocus prevention _will_ be done again.
763
764 **Warning:** There are also properties starting with an underscore on `vim`
765 objects. They are private, and not supposed to be used outside of VimFx’s own
766 source code. They may change at any time.
767
768 ### Options object
769
770 An `options` object provides access to all of VimFx’s options. It is an object
771 whose keys are VimFx option names.
772
773 Note that the values are not just simply `vimfx.get(option)` for the `option` in
774 question; they are _parsed_ (`parse(vimfx.get(option))`):
775
776 - Space-separated options are parsed into arrays of strings. For example,
777 `pattern_attrs: ['class']`.
778
779 - `blacklist`, `prev_patterns` and `next_patterns` are parsed into arrays of
780 regular expressions. For example, `prev_patterns: [/\bnavPrev\b/]`.
781
782 (See [parse-prefs.coffee] for all details.)
783
784 Any [option overrides] are automatically taken into account when getting an
785 option value.
786
787 The [special options] are also available on this object.
788
789
790 ### Location object
791
792 A location object is very similar to [`window.location`] in web pages.
793 Technically, it is a [`URL`] instance. You can experiment with the current
794 location object by opening the [web console] and entering `location`.
795
796
797 ## `frame.js` API
798
799 In `frame.js`, the following API is available as the variable `vimfx`.
800
801 ### `vimfx.listen(message, listener)`
802
803 Listen for `message` (a string) from `config.js`. `listener` will be called with
804 the data sent from `config.js` (if any), and optionally a callback function if
805 `config.js` wants you to respond. If so, call the callback function, optionally
806 with some data to send back to `config.js.` `config.js` uses its
807 [`vimfx.send(...)`] method to send `message` (and optionally some data along
808 with it).
809
810 See the [`vimfx.send(...)`] method in `config.js` for more information and
811 examples.
812
813 ### `vimfx.setHintMatcher(hintMatcher)`
814
815 `hintMatcher` is a function that lets you customize which elements do and don’t
816 get hints. It might help to read about [the hint commands] first.
817
818 If you call `vimfx.setHintMatcher(hintMatcher)` more than once, only the
819 `hintMatcher` provided the last time will be used.
820
821 ```js
822 vimfx.setHintMatcher((id, element, type) => {
823 // Inspect `element` and return a different `type` if needed.
824 return type
825 })
826 ```
827
828 The arguments passed to the `hintMatcher` function are:
829
830 - id: `String`. A string identifying which command is used:
831
832 - `'normal'`: `f` or `af`.
833 - `'tab'`: `F`, `et`, `ew` or `ep`.
834 - `'copy'`: `yf`.
835 - `'focus'`: `ef`.
836 - `'context'`: `ec`.
837 - `'select'`: `v`, `av` or `yv`.
838
839 - element: `Element`. One out of all elements currently inside the viewport.
840
841 - type: `String` or `null`. If a string, it means that `element` should get a
842 hint. If `null`, it won’t. See the available strings below. When a marker
843 is matched, `type` decides what happens to `element`.
844
845 This parameter tells how VimFx has matched `element`. You have the opportunity
846 to change that.
847
848 The available type strings depend on `id`:
849
850 - normal:
851
852 - link: A “proper” link (not used as a button with the help of JavaScript),
853 with an `href` attribute.
854 - text: An element that can you can type in, such as text inputs.
855 - clickable: Some clickable element not falling into another category.
856 - clickable-special: Like “clickable,” but uses a different technique to
857 simulate a click on the element. If “clickable” doesn’t work, try this one.
858 - scrollable: A scrollable element.
859
860 - tab:
861
862 - link: Like “link” when `id` is “normal” (see above).
863
864 - copy:
865
866 - link: Like “link” when `id` is “normal” (see above).
867 - text: Like “text” when `id` is “normal” (see above), except that in this
868 case “contenteditable” elements are not included.
869 - contenteditable: Elements with “contenteditable” turned on.
870
871 - focus:
872
873 - focusable: Any focusable element not falling into another category.
874 - scrollable: Like “scrollable” when `id` is “normal” (see above).
875
876 - context:
877
878 - context: An element that can have a context menu opened.
879
880 - select:
881
882 - selectable: An element with selectable text (but not text inputs).
883
884 The function must return `null` or a string like the `type` parameter.
885
886 ### `vimfx.getMarkerElement(id)`
887
888 Takes an id that has been given to you when creating [custom hint commands] and
889 returns the DOM element associated with that id. If no element can be found,
890 `null` is returned.
891
892
893 ## Stability
894
895 The API is currently **experimental** and therefore **unstable.** Things might
896 break with new VimFx versions. However, no breaking changes are planned, and
897 will be avoided if feasible.
898
899 As soon as VimFx 1.0.0 (which does not seem to be too far away) is released
900 backwards compatibility will be a priority and won’t be broken until VimFx
901 2.0.0.
902
903 [option overrides]: #vimfxaddoptionoverridesrules
904 [`vimfx.send(...)`]: #vimfxsendvim-message-data--null-callback--null
905 [`vimfx.listen(...)`]: #vimfxlistenmessage-listener
906 [categories]: #vimfxgetcategories
907 [custom hint commands]: #custom-hints-commands
908 [`vimfx.modes`]: #vimfxmodes
909 [onInput]: #oninput
910 [mode object]: #mode-object
911 [category object]: #category-object
912 [command object]: #command-object
913 [match object]: #match-object
914 [vim object]: #vim-object
915 [options object]: #options-object
916 [location object]: #location-object
917 [The `focusTypeChange` event]: #the-focustypechange-event
918 [the `shutdown` event]: #the-shutdown-event
919 [`vimfx.setHintMatcher(...)`]: #vimfxsethintmatcherhintmatcher
920 [`vimfx.getMarkerElement(...)`]: #vimfxgetmarkerelementid
921
922 [blacklisted]: options.md#blacklist
923 [special options]: options.md#special-options
924 [config file]: config-file.md
925 [bootstrap.js]: config-file.md#bootstrapjs
926 [autofocus prevention]: options.md#prevent-autofocus
927 [`activatable_element_keys`]: options.md#activatable_element_keys
928 [`adjustable_element_keys`]: options.md#adjustable_element_keys
929 [`blur_timeout`]: options.md#blur_timeout
930 [`notifications_enabled`]: options.md#notifications_enabled
931
932 [button]: button.md
933 [the hint commands]: commands.md#the-hint-commands--hints-mode
934 [special keys]: shortcuts.md#special-keys
935 [styling]: styling.md
936
937 [defaults.coffee]: ../extension/lib/defaults.coffee
938 [parse-prefs.coffee]: ../extension/lib/parse-prefs.coffee
939 [modes.coffee]: ../extension/lib/modes.coffee
940 [commands.coffee]: ../extension/lib/commands.coffee
941 [vim.coffee]: ../extension/lib/vim.coffee
942
943 [`event.key`]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
944 [`event.code`]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code
945 [`Window`]: https://developer.mozilla.org/en-US/docs/Web/API/Window
946 [`Browser`]: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/browser
947 [`window.location`]: https://developer.mozilla.org/en-US/docs/Web/API/Location
948 [`URL`]: https://developer.mozilla.org/en-US/docs/Web/API/URL
949 [Message Manager]: https://developer.mozilla.org/en-US/Firefox/Multiprocess_Firefox/Message_Manager
950 [TabSelect]: https://developer.mozilla.org/en-US/docs/Web/Events/TabSelect
951 [web console]: https://developer.mozilla.org/en-US/docs/Tools/Web_Console
952 [about:config]: http://kb.mozillazine.org/About:config
Imprint / Impressum